花了N久时间,终于把这个难啃的骨头啃下来了。

建议大家学习fft时,千万不要到网上找各种快速傅里叶变换的解释,那实在是令人难以理解。

可以查阅《算法导论》并结合洛谷模板里的题解,可以深入理解多项式乘法的算法。

这里是一个可以用的板子。

#include<iostream>
#include<cstdio>
#include<climits>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
const int M=3e6;
struct cp{//最好手打一遍复数complex类型,反正也就几行
    double x,y;
    cp(double xx=0,double yy=0){
        x=xx;y=yy;
    }
    cp operator+(const cp&a){
        return cp(x+a.x,y+a.y);
    }
    cp operator-(const cp&a){
        return cp(x-a.x,y-a.y);
    }
    cp operator*(const cp&a){
        return cp(x*a.x-y*a.y,x*a.y+y*a.x);
    }
}a[M],b[M];
int r[M];
int limit=1,l=0;

void fft(cp*a,int f){//不理解的话——背!代!码!
    rep(i,0,limit-1)if(i<r[i])swap(a[i],a[r[i]]);
    for(int mid=1;mid<limit;mid<<=1){
        cp wn(cos(M_PI/mid),f*sin(M_PI/mid));//单位根
        for(int j=0,R=mid<<1;j<limit;j+=R){
            cp w(1,0);
            for(int k=0;k<mid;k++,w=w*wn){
                cp x=a[j+k],y=w*a[j+mid+k];
                a[j+k]=x+y;a[j+mid+k]=x-y;
            }
        } 
    }
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    rep(i,0,n)scanf("%lf",&a[i].x);
    rep(i,0,m)scanf("%lf",&b[i].x);
    while(limit<=n+m)limit<<=1,l++;
    l--;
    rep(i,0,limit-1)r[i]=(r[i>>1]>>1)|((i&1)<<l);
    fft(a,1);fft(b,1);
    rep(i,0,limit)a[i]=a[i]*b[i];
    fft(a,-1);
    rep(i,0,n+m)printf("%d ",(int)(a[i].x/limit+0.5));
    return 0;
}