题面
题解
fft模板题
单向膜拜:
大致理解为将多项式从系数表示法转化为点值表示法然后再变回系数表示法
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 2621450
#define pi acos(-1.0)
using namespace std;
int n,m,len,R[N];
struct com{
double r,i;
com(){}
com(double a,double b):r(a),i(b){}
}a[N],b[N];
inline com operator + (const com a,const com b){return com(a.r+b.r,a.i+b.i);}
inline com operator - (const com a,const com b){return com(a.r-b.r,a.i-b.i);}
inline com operator * (const com a,const com b){
return com(a.r*b.r-a.i*b.i,a.i*b.r+a.r*b.i);
}
inline int read(){
int a=0;char f=1,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}
return a*f;
}
inline void FFT(com *a,int f){
for(int i=0;i<n;++i) if(i<R[i]) swap(a[i],a[R[i]]); //找最终位置
for(int k=1;k<n;k<<=1){
com wn(cos(pi/k),f*sin(pi/k));
for(int i=0;i<n;i+=k<<1){
com w(1,0),x,y;
for(int j=0;j<k;++j,w=w*wn)
x=a[i+j],y=w*a[i+j+k],a[i+j]=x+y,a[i+j+k]=x-y; //蝴蝶操作
}
}
if(f==-1) for(int i=0;i<n;++i) a[i].r=a[i].r/n;
}
int main(){
freopen("testdata.in","r",stdin);
// freopen("testdata.out","w",stdout);
n=read(),m=read();
for(int i=0;i<=n;++i) a[i].r=read();
for(int i=0;i<=m;++i) b[i].r=read();
m+=n;for(n=1;n<=m;n<<=1) ++len;
for(int i=0;i<n;++i) R[i]=(R[i>>1]>>1)|((i&1)<<(len-1)); //二进制位翻转
FFT(a,1),FFT(b,1);
for(int i=0;i<n;++i) a[i]=a[i]*b[i];
FFT(a,-1); //逆变换得到系数
for(int i=0;i<=m;++i) printf("%d%s",(int)(a[i].r+0.5),i==n?"\n":" ");
return 0;
}