https://www.luogu.com.cn/problem/P3803
题目背景
这是一道多项式乘法模板题
题目描述
给定一个 n 次多项式 F(x),和一个 m 次多项式 G(x)。
请求出 F(x) 和 G(x) 的卷积。
输入格式
第一行两个整数 n,mn,m。
接下来一行 n+1 个数字,从低到高表示 F(x)F(x) 的系数。
接下来一行 m+1 个数字,从低到高表示 G(x)G(x) 的系数。
输出格式
一行 n+m+1n+m+1 个数字,从低到高表示 F(x) \cdot G(x)F(x)⋅G(x) 的系数。
输入输出样例
输入 #1复制
1 2
1 2
1 2 1
输出 #1复制
1 4 5 2
说明/提示
保证输入中的系数大于等于 0 且小于等于 9。
对于 100%100% 的数据: 1 ≤ n , m ≤ 10 6 1 \le n, m \leq {10}^6 1≤n,m≤106。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define MOD 1000000007
using namespace std; //FFT模板
const int maxn=1e6+5;
struct Complex
{
double x,y;
Complex(double dx=0,double dy=0)
{
x=dx;
y=dy;
}
};
Complex operator +(Complex a,Complex b)
{
return Complex(a.x+b.x,a.y+b.y);
}
Complex operator -(Complex a,Complex b)
{
return Complex(a.x-b.x,a.y-b.y);
}
Complex operator *(Complex a,Complex b)
{
return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
const double pi=acos(-1.0); //PI
int limit=1,bit=0;
int wz[maxn<<2];
Complex a[maxn<<2],b[maxn<<2];
void FFT(Complex *A,int inv)
{
for(int i=0;i<limit;i++)
if(i<wz[i])
swap(A[i],A[wz[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
Complex wn(cos(pi/mid),inv*sin(pi/mid));
for(int i=0;i<limit;i+=mid<<1)
{
Complex w(1,0);
for(int j=0;j<mid;j++,w=w*wn)
{
Complex t1=A[i+j];
Complex t2=w*A[i+mid+j];
A[i+j]=t1+t2;
A[i+mid+j]=t1-t2;
}
}
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)) //两个多项式的长度
{
memset(wz,0,sizeof(wz));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
limit=1,bit=0;
int len=n+m;
while(limit<=len)
{
limit<<=1;
bit++;
}
int v;
for(int i=0;i<=n;i++) //从低位到高位
{
scanf("%d",&v);
a[i].x=v;
}
for(int i=0;i<=m;i++) //从低位到高位
{
scanf("%d",&v);
b[i].x=v;
}
for(int i=0;i<limit;i++)
wz[i]=(wz[i>>1]>>1)|((i&1)<<(bit-1));
FFT(a,1);
FFT(b,1);
for(int i=0;i<limit;i++)
a[i]=a[i]*b[i];
FFT(a,-1);
printf("%d",(int)(a[0].x/limit+0.5));
for(int i=1;i<=len;i++) //从低位到高位
printf(" %d",(int)(a[i].x/limit+0.5));
putchar('\n');
}
return 0;
}