题目背景
这是一道FFT模板题
注意:虽然本题开到3s,但是建议程序在1s内可以跑完,本题需要一定程度的常数优化。
题目描述
给定一个n次多项式F(x),和一个m次多项式G(x)。
请求出F(x)和G(x)的卷积。
输入输出格式
输入格式:第一行2个正整数n,m。
接下来一行n+1个数字,从低到高表示F(x)的系数。
接下来一行m+1个数字,从低到高表示G(x))的系数。
输出格式:一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数。
输入输出样例
说明
保证输入中的系数大于等于 0 且小于等于9。
对于100%的数据: n, m \leq {10}^6n,m≤106 , 共计20个数据点,2s。
数据有一定梯度。
空间限制:256MB
题解:FFT模板
代码:
#include<bits/stdc++.h>
using namespace std;
struct cp{
double x,y;
cp(double xx=0,double yy=0){
x=xx;y=yy;
}
}a[4000001],b[4000001];
cp operator + (cp a,cp b){
return cp(a.x+b.x,a.y+b.y);
}
cp operator - (cp a,cp b){
return cp(a.x-b.x,a.y-b.y);
}
cp operator * (cp a,cp b){
return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
const double pi=acos(-1.0);
int n,m,i,limit,r[4000001],l;
void FFT(cp *A,int type){
for(int i=0;i<limit;i++)
if(i<r[i])swap(A[i],A[r[i]]);
for(int mid=1;mid<limit;mid<<=1){
cp Wn(cos(pi/mid),type*sin(pi/mid));
for(int R=mid<<1,j=0;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 i;
limit=1;
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++)scanf("%lf",&a[i].x);
for(i=0;i<=m;i++)scanf("%lf",&b[i].x);
while(limit<=n+m){
limit<<=1;
l++;
}
for(i=0;i<limit;i++)
r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
FFT(a,1);
FFT(b,1);
for(i=0;i<=limit;i++)a[i]=a[i]*b[i];
FFT(a,-1);
for(i=0;i<=n+m;i++)printf("%d ",(int)(a[i].x/limit+0.5));
}