[BZOJ2194] FFT卷积

来源:互联网 发布:网络包装公司是干嘛的 编辑:程序博客网 时间:2024/05/18 11:22

fft板子易错点:
1、bit为最长的多项式的位数
2、maxn> (1<< bit)
3、fft中第一层循环i表示两个i长度的块并成一个 2i 长度的块,所以wn为 2i的单位根,j也是+=2i。
4、记得idft的情况
代码:

#include<iostream>#include<cstdio>#include<cmath>#include<complex>using namespace std;const int maxn=280010;//maxn>2^(2*n) const double pi=acos(-1);typedef complex<double> cd;cd a[maxn],b[maxn];int n,r[maxn];void getrev(int bit){    for(int i=0;i<(1<<bit);i++)        r[i]=(r[i>>1]>>1)+((i&1)<<(bit-1));}void fft(cd *a,int n,int dft){    for(int i=0;i<n;i++)        if(i<r[i]) swap(a[i],a[r[i]]);    for(int i=1;i<n;i<<=1)//two i-area combine to an 2*i-area    {        cd wn=exp(cd(0,dft*pi/i));//dft*2*pi/(2*i)         for(int j=0;j<n;j+=(i<<1))//j+=2*i        {            cd wnk=cd(1,0);            for(int k=j;k<j+i;k++)            {                cd x=a[k],y=wnk*a[k+i];                a[k]=x+y;                a[k+i]=x-y;                wnk*=wn;            }        }    }    if(dft==-1) for(int i=0;i<n;i++) a[i]/=n;}int main(){    scanf("%d",&n);    int x,y;    for(int i=0;i<n;i++)        {scanf("%d%d",&x,&y);a[i]=x;b[n-1-i]=y;}    int bit=0;    while((1<<bit)<2*n-2)   bit++;//(1<<bit)>2^(2*n)    getrev(bit);    fft(a,(1<<bit),1);    fft(b,(1<<bit),1);    for(int i=0;i<(1<<bit);i++)        a[i]*=b[i];    fft(a,(1<<bit),-1);    for(int i=n-1;i<=2*n-2;i++)        printf("%d\n",(int)round(a[i].real()));    return 0;}/*53 12 41 12 41 4*/
原创粉丝点击