FFT及NTT模板

来源:互联网 发布:免费手机绿色上网软件 编辑:程序博客网 时间:2024/04/26 09:03

FFT

其中2ce=len
无视这个板子,FFT照着NTT写就行了。
w[0]=(1,0)
w[1]=(cos(2*pi/len),sin(2*pi/len))

void DFT(node *a,int sig){    fo(i,0,len-1){        int p=0;        for(int j=0,tp=i;j<ce;j++,tp/=2) p=(p<<1)+(tp%2);        tt[p]=a[i];    }    for(int m=2;m<=len;m*=2){        int half=m/2;        fo(i,0,half-1){            node w;            w.x=cos(i*sig*pi/half),w.y=sin(i*sig*pi/half);            for(int j=i;j<len;j+=m){                node u=tt[j],v=tt[j+half]*w;                tt[j]=u+v;                tt[j+half]=u-v;            }        }    }    if (sig==-1)        fo(i,0,len-1) tt[i].x/=len;    fo(i,0,len-1) a[i]=tt[i];}void FFT(node *a,node *b,node *c){    int i;    fo(i,0,len-1) e[i]=a[i],f[i]=b[i];    DFT(e,1);DFT(f,1);    fo(i,0,len-1) e[i]=e[i]*f[i];    DFT(e,-1);    fo(i,0,len-1) c[i]=e[i];}

NTT

考虑相对于FFT变化的地方。
ce的意义没有变化,其中,w数组需要预处理,w[i]=w[1]i
ni则表示len关于模数的逆元。

void DFT(int *a,int sig){    int i;    fo(i,0,len-1){        int p=0;        for(int j=0,tp=i;j<ce;j++,tp/=2) p=(p<<1)+(tp%2);        tt[p]=a[i];    }    for (int m=2;m<=len;m*=2){        int half=m/2,bei=len/m;        fo(i,0,half-1){            int wi=sig>0?w[i*bei]:w[len-i*bei];            for(int j=i;j<len;j+=m){                int u=tt[j],v=(ll)tt[j+half]*wi%mo;                tt[j]=(u+v)%mo;                tt[j+half]=(u-v)%mo;            }        }    }    if (sig==-1)        fo(i,0,len-1) tt[i]=(ll)tt[i]*ni%mo;    fo(i,0,len-1) a[i]=tt[i];}void NTT(int *a,int *b,int *c){    int i;    fo(i,0,len-1) A[i]=a[i],B[i]=b[i];    DFT(A,1);DFT(B,1);    fo(i,0,len-1) A[i]=(ll)A[i]*B[i]%mo;    DFT(A,-1);    fo(i,0,len-1) c[i]=A[i];}

预处理部分

    len=1;    while (len<=n*2) len*=2;    ni=quicksortmi(len,mo-2);    ce=(db)log(len)/log(2);    w[0]=1;    w[1]=quicksortmi(GG,(mo-1)/len);    fo(i,2,len) w[i]=(ll)w[i-1]*w[1]%mo;

GG表示模数的一个原根

0 0
原创粉丝点击