[模板] 快速傅里叶变换/fft

Code

const int nmax=(int)3e6+50;
const db pi=acos(-1.0);

struct tcpx{db a,b;}c1[nmax],c2[nmax];
tcpx operator+(tcpx a,tcpx b){return (tcpx){a.a+b.a,a.b+b.b};}
tcpx operator-(tcpx a,tcpx b){return (tcpx){a.a-b.a,a.b-b.b};}
tcpx operator*(tcpx a,tcpx b){return (tcpx){a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}

int n,m;
int l,rev[nmax];
void dft(tcpx *c,int n,int fl){
    rep(i,0,n-1)if(i<rev[i])swap(c[i],c[rev[i]]);
    for(int i=1;i<n;i<<=1){
        tcpx wn=(tcpx){cos(pi/i),fl*sin(pi/i)};
        for(int j=0,p=(i<<1);j<n;j+=p){
            tcpx w=(tcpx){1,0};
            for(int k=0;k<i;++k,w=w*wn){
                tcpx x=c[j+k],y=w*c[j+k+i];
                c[j+k]=x+y,c[j+k+i]=x-y;
            }
        }
    }
}
void fft(tcpx *c1,int n,tcpx *c2,int m,tcpx *c3){//c3=c1*c2
    m+=n;
    for(n=1;n<=m;n<<=1)++l;
    rep(i,0,n-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    dft(c1,n,1),dft(c2,n,1);
    rep(i,0,n-1)c3[i]=c1[i]*c2[i];
    dft(c3,n,-1);
    rep(i,0,n-1)c3[i].a=(int)(c3[i].a/n+0.5);
}

猜你喜欢

转载自www.cnblogs.com/ubospica/p/10279351.html