-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathfft.cpp
72 lines (72 loc) · 1.96 KB
/
fft.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// MAXN must be power of 2 !!
// MOD-1 needs to be a multiple of MAXN !!
// big mod and primitive root for NTT:
typedef ll tf;
typedef vector<tf> poly;
const tf MOD=2305843009255636993,RT=5;
// FFT
struct CD {
double r,i;
CD(double r=0, double i=0):r(r),i(i){}
double real()const{return r;}
void operator/=(const int c){r/=c, i/=c;}
};
CD operator*(const CD& a, const CD& b){
return CD(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);}
CD operator+(const CD& a, const CD& b){return CD(a.r+b.r,a.i+b.i);}
CD operator-(const CD& a, const CD& b){return CD(a.r-b.r,a.i-b.i);}
const double pi=acos(-1.0);
// NTT
/*
struct CD {
tf x;
CD(tf x):x(x){}
CD(){}
};
CD operator*(const CD& a, const CD& b){return CD(mulmod(a.x,b.x));}
CD operator+(const CD& a, const CD& b){return CD(addmod(a.x,b.x));}
CD operator-(const CD& a, const CD& b){return CD(submod(a.x,b.x));}
vector<tf> rts(MAXN+9,-1);
CD root(int n, bool inv){
tf r=rts[n]<0?rts[n]=pm(RT,(MOD-1)/n):rts[n];
return CD(inv?pm(r,MOD-2):r);
}
*/
CD cp1[MAXN+9],cp2[MAXN+9];
int R[MAXN+9];
void dft(CD* a, int n, bool inv){
fore(i,0,n)if(R[i]<i)swap(a[R[i]],a[i]);
for(int m=2;m<=n;m*=2){
double z=2*pi/m*(inv?-1:1); // FFT
CD wi=CD(cos(z),sin(z)); // FFT
// CD wi=root(m,inv); // NTT
for(int j=0;j<n;j+=m){
CD w(1);
for(int k=j,k2=j+m/2;k2<j+m;k++,k2++){
CD u=a[k];CD v=a[k2]*w;a[k]=u+v;a[k2]=u-v;w=w*wi;
}
}
}
if(inv)fore(i,0,n)a[i]/=n; // FFT
//if(inv){ // NTT
// CD z(pm(n,MOD-2)); // pm: modular exponentiation
// fore(i,0,n)a[i]=a[i]*z;
//}
}
poly multiply(poly& p1, poly& p2){
int n=p1.size()+p2.size()+1;
int m=1,cnt=0;
while(m<=n)m+=m,cnt++;
fore(i,0,m){R[i]=0;fore(j,0,cnt)R[i]=(R[i]<<1)|((i>>j)&1);}
fore(i,0,m)cp1[i]=0,cp2[i]=0;
fore(i,0,p1.size())cp1[i]=p1[i];
fore(i,0,p2.size())cp2[i]=p2[i];
dft(cp1,m,false);dft(cp2,m,false);
fore(i,0,m)cp1[i]=cp1[i]*cp2[i];
dft(cp1,m,true);
poly res;
n-=2;
fore(i,0,n)res.pb((tf)floor(cp1[i].real()+0.5)); // FFT
//fore(i,0,n)res.pb(cp1[i].x); // NTT
return res;
}