BZOJ 2194: 快速傅立叶之二
题目大意:
计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n 。
题解:
把b倒过来,求卷积,FFT。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define pi acos(-1) using namespace std; struct node{ double x,i; node(){} node(double x,double i):x(x),i(i){} node operator+(node a) {return node(x+a.x,i+a.i);} node operator-(node a) {return node(x-a.x,i-a.i);} node operator*(node a) {return node(x*a.x-i*a.i,x*a.i+i*a.x);} }a[300005],b[300005]; int rev[300005]; void fft(node *a,int n,int t) { for (int i=0; i<n; i++) if (i<rev[i]) swap(a[i],a[rev[i]]); for (int j=1; j<n; j<<=1) { node wn(cos(2*pi/(j<<1)),t*sin(2*pi/(j<<1))); for (int i=0; i<n; i+=(j<<1)) { node w(1,0),t0,t1; for (int k=0; k<j; k++,w=w*wn) { t0=a[i+k]; t1=w*a[i+j+k]; a[i+k]=t0+t1; a[i+j+k]=t0-t1; } } } } int main() { int n; scanf("%d",&n); n--; for (int i=0; i<=n; i++) scanf("%lf%lf",&a[i].x,&b[n-i].x); int nn=1,len=0; while (nn<=2*n){ nn<<=1; len++; } rev[0]=0; for (int i=1; i<nn; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1)); fft(a,nn,1); fft(b,nn,1); for (int i=0; i<=nn; i++) a[i]=a[i]*b[i]; fft(a,nn,-1); for (int i=n; i<=2*n; i++) printf("%d\n",(int)(a[i].x/nn+0.5)); return 0; }