[uoj#34] [洛谷P3803] 多项式乘法(FFT)

Posted 秋千旁的蜂蝶~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[uoj#34] [洛谷P3803] 多项式乘法(FFT)相关的知识,希望对你有一定的参考价值。

新技能——FFT。
可在 \(O(nlogn)\) 时间内完成多项式在系数表达与点值表达之间的转换。
其中最关键的一点便为单位复数根,有神奇的折半性质。
多项式乘法(即为卷积)的常见形式:
\[ C_n=\sum\limits_{i=0}^n A_iB_{n-i} \]
基本思路为先将系数表达 -> 点值表达 \(O(nlogn)\)
随后点值 \(O(n)\) 进行乘法运算
最后将点值表达 -> 系数表达 \(O(nlogn)\)


代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>

using namespace std;

const int N = 2100005;
const double pi = 3.1415926535897932384626433832795;

struct c{
    double r,i;
    c() { r=i=0.0; }
    c(double x,double y) { r=x; i=y; }
    c operator + (const c &b) { return c(r+b.r,i+b.i); }
    c operator += (const c &b) { return *this=*this+b; }
    c operator - (const c &b) { return c(r-b.r,i-b.i); }
    c operator -= (const c &b) { return *this=*this-b; }
    c operator * (const c &b) { return c(r*b.r-i*b.i,r*b.i+b.r*i); }
    c operator *= (const c &b) { return *this=*this*b; }
}a[N],b[N],x[N];

int l;
int r[N];
void fft(c A[],int ty){
    for(int i=0;i<l;i++) x[r[i]]=A[i];
    for(int i=0;i<l;i++) A[i]=x[i];
    for(int i=2;i<=l;i<<=1){
        c wn(cos(pi*2/i),ty*sin(pi*2/i));
        for(int j=0;j<l;j+=i){
            c w(1,0);
            for(int k=j;k<j+i/2;k++){
                c t=A[k+i/2]*w;
                A[k+i/2]=A[k]-t;
                A[k]+=t;
                w*=wn;
            }
        }
    }
}

int n,m;

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++) scanf("%lf",&a[i].r);
    for(int i=0;i<=m;i++) scanf("%lf",&b[i].r);
    
    l=1;
    while(l<=n+m) l<<=1;
    for(int i=0;i<l;i++) r[i]=(r[i>>1]>>1)|((i&1)*(l>>1));
    
    fft(a,1);fft(b,1);
    for(int i=0;i<l;i++)
        a[i]*=b[i];
    fft(a,-1);
    
    for(int i=0;i<n+m;i++)
        printf("%d ",int(a[i].r/l+0.5));
    printf("%d",int(a[n+m].r/l+0.5));
   
    return 0;    
}

以上是关于[uoj#34] [洛谷P3803] 多项式乘法(FFT)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P3803 模板多项式乘法(FFT) fft

uoj34 多项式乘法

uoj#34. 多项式乘法

UOJ #34 多项式乘法

[模板][P3803]多项式乘法

●UOJ 34 多项式乘法