【BZOJ】【2194】快速傅里叶之二
FFT
c[k]=sigma a[i]*b[i-k] 这个形式不好搞……
而我们熟悉的卷积的形式是这样的 c[k]=sigma a[i]*b[k-i]也就是【下标之和是定值】
所以我们将a数组反转一下就可以卷积了=。=
1 /************************************************************** 2 Problem: 2194 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:2008 ms 7 Memory:48148 kb 8 ****************************************************************/ 9 10 //BZOJ 2194 11 #include<cmath> 12 #include<cstdio> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 using namespace std; 21 int getint(){ 22 int v=0,sign=1; char ch=getchar(); 23 while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();} 24 while(isdigit(ch)) {v=v*10+ch-'0'; ch=getchar();} 25 return v*sign; 26 } 27 /*******************template********************/ 28 const int N=1000010; 29 const double pi=acos(-1); 30 struct comp{ 31 double r,i; 32 // comp(){} 33 comp(double _=0.0,double __=0.0) : r(_),i(__){} 34 comp operator + (const comp &b)const{return comp(r+b.r,i+b.i);} 35 comp operator - (const comp &b)const{return comp(r-b.r,i-b.i);} 36 comp operator * (const comp &b)const{return comp(r*b.r-i*b.i,r*b.i+i*b.r);} 37 }a[N],b[N],c[N]; 38 void FFT(comp *a,int n,int type){ 39 for(int i=1,j=0;i<n-1;++i){ 40 for(int s=n;j^=s>>=1,~j&s;); 41 if(i<j) swap(a[i],a[j]); 42 } 43 for(int m=1;m<n;m<<=1){ 44 double u=pi/m*type; comp wm(cos(u),sin(u)); 45 for(int i=0;i<n;i+=(m<<1)){ 46 comp w(1,0); 47 rep(j,m){ 48 comp &A=a[i+j+m], &B=a[i+j], t=w*A; 49 A=B-t; B=B+t; w=w*wm; 50 } 51 } 52 } 53 if (type==-1) rep(i,n) a[i].r/=n; 54 } 55 56 int main(){ 57 int n=getint(); 58 rep(i,n){ 59 a[n-i-1].r=getint(); 60 b[i].r=getint(); 61 } 62 int len=1; 63 for(len=1;len<=n<<1;len<<=1); 64 FFT(a,len,1); FFT(b,len,1); 65 rep(i,len) c[i]=a[i]*b[i]; 66 FFT(c,len,-1); 67 D(i,n-1,0) printf("%d\n",int(c[i].r+0.5) ); 68 return 0; 69 }