题目大意:
计算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;
}