FFT入门及其套路

 FFT原理详解,包含大数乘法的代码

https://www.cnblogs.com/RabbitHu/p/FFT.html

多项式乘法:就是套一套板子:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define N 2000005

struct complex{
    double x,y;
    complex (double xx=0,double yy=0){x=xx,y=yy;}
};
complex operator + (complex a,complex b){ return complex(a.x+b.x , a.y+b.y);}
complex operator - (complex a,complex b){ return complex(a.x-b.x , a.y-b.y);}
complex operator * (complex a,complex b){ return complex(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);}

typedef complex cp;
const double pi = acos(-1.0);
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
ll A[N],B[N],lena,lenb,n,res[N];
cp a[N],b[N],omg[N],inv[N];

void init(){//预处理出单位根及其倒数 
    for(register int i=0;i<n;i++)
        omg[i]=cp(cos(2*pi/n*i),sin(2*pi/n*i));
    for(register int i=0;i<n;i++)
        inv[i]=cp(cos(2*pi/n*i),-sin(2*pi/n*i));
}

void fft(cp *a, cp *omg){
    int lim = 0;
    while((1<<lim)<n)lim++;    //向下分治的次数 
    for(register int i=0;i<n;i++){    //先把系数移到最后一层递归的位置 
        int t=0;
        for(register int j=0;j<lim;j++)
            if((i>>j) & 1) t|=(1<<(lim-j-1));
        if(i<t)swap(a[i],a[t]);
    }
    for(register int l=2;l<=n;l*=2){    //每个递归区间的长度 
        int m=l/2;
        for(cp *p=a;p!=a+n;p+=l)
            for(register int i=0;i<m;i++){//蝴蝶操作 
                cp t=omg[n/l*i]*p[i+m];
                p[i+m]=p[i]-t;
                p[i]=p[i]+t; 
            }
    }
    
}

//a0,a1,a2,a3...an

int main(){
    lena=read();lenb=read();
    lena++;lenb++;
    n=1;while(n<lena+lenb)n<<=1;
    for(register int i=0;i<lena;i++)A[i]=read();
    for(register int i=0;i<lenb;i++)B[i]=read();
    for(register int i=0;i<lena;i++)a[i]=cp(A[i],0);
    for(register int i=0;i<lenb;i++)b[i]=cp(B[i],0);
    init();
    fft(a,omg);fft(b,omg);
    for(register int i=0;i<n;i++)a[i]=a[i]*b[i];
    fft(a,inv);
        
    for(register int i=0;i<n;i++)
        res[i]=floor(a[i].x/n+0.5);
    for(register int i=0;i<lena+lenb-1;i++)
        cout<<res[i]<<" ";
        
}
View Code

多项式乘法的卷积形式

https://www.cnblogs.com/RabbitHu/p/BZOJ2194.html

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12304340.html
FFT
今日推荐