中午看着题解打完了。。晚上才想清白。。
题目都说了fft肯定就把式子往卷积上转啦。
然而题目中是求下标差一定的两个多项式的乘积和,那么就把
a
或者
假设反
b
那么
令
D[k]=∑n−1i=ka[i]∗b[k−i]
那么
C[k]=D[n+k]
发现求
Dk
的式子很像卷积啊,然而正常卷积不应该是
∑ki=0
吗。。
就是这个东西纠结了我很久。。其实把对应的项写出来。。发现其余的都是0毫无影响。。
D[n+k]=∑n+ki=0a[i]∗b[n+k−i]
【代码】
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <complex>
#include <algorithm>
#include <cmath>
#define N 262145
#define INF 0x7fffffff
using namespace std;
typedef complex<double> C;
const double pi=acos(-1);
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m;
C a[N],b[N];
void FFT(C *a,int n,int f)
{
if(n==1) return;
C wn(cos(2*pi/n),sin(2*pi*f/n)),w(1,0),t;
C a0[n>>1],a1[n>>1];
for(int i=0;i<n>>1;i++) a0[i]=a[i<<1],a1[i]=a[i<<1|1];
FFT(a0,n>>1,f),FFT(a1,n>>1,f);
for(int i=0;i<n>>1;i++,w*=wn)
{
t=a1[i]*w;
a[i]=a0[i]+t;
a[i+(n>>1)]=a0[i]-t;
}
}
int main()
{
n=m=read()-1;
for(int i=0;i<=n;i++)
{
a[i]=read();
b[n-i]=read();
}
m+=n;
for(n=1;n<=m;n<<=1);
FFT(a,n,1);FFT(b,n,1);
for(int i=0;i<=n;i++) a[i]*=b[i];
FFT(a,n,-1);
for(int i=m>>1;i<=m;i++) printf("%d\n",int(a[i].real()/n+0.5));
return 0;
}