1449: 【快速傅立葉變換(模版題)】多項式乘法
阿新 • • 發佈:2019-02-20
時間限制: 1 Sec 記憶體限制: 256 MB
提交: 44 解決: 14
[提交][狀態][討論版]
題目描述
【題意】
給你兩個多項式,請輸出乘起來後的多項式。
【輸入】
第一行兩個整數 n 和 m,分別表示兩個多項式的次數。1<=n,m<=10^5
第二行 n+1 個整數,分別表示第一個多項式的 0 到 n次項前的係數。
第三行 m+1 個整數,分別表示第一個多項式的 0 到 m 次項前的係數。
【輸出】
一行 n+m+1 個整數,分別表示乘起來後的多項式的 0 到 n+m 次項前的係數。
【樣例輸入】
1 2
1 2
1 2 1
【樣例輸出】
1 4 5 2
本篇部落格介紹的是迭代的方法,自己建立的Complex,較為重要的地方帶有註釋。
#include<iostream>
#include<cstdio>
using namespace std;
#include <cmath>
double PI =acos(-1);
const int MAXN =4*1e5+10;
int r[MAXN];
struct Complex
{
double r,i;
Complex(){}
Complex(double _r,double _i){ r=_r,i=_i;}
Complex operator +(const Complex &y){ return Complex(r+y.r,i+y.i);}
Complex operator -(const Complex &y){return Complex(r-y.r,i-y.i);}
Complex operator *(const Complex &y){return Complex(r*y.r-i*y.i,r*y.i+i*y.r);}
Complex operator *=(const Complex &y){double t=r;r=r*y.r-i*y.i,i=t*y.i+i*y.r;}
} a[MAXN],b[MAXN];
void fft(Complex *a,int len,int op)
{
Complex tt;
for(int i=0;i<len;i++)if(i<r[i])
tt=a[i],a[i]=a[r[i]],a[r[i]]=tt;
for(int i=1;i<len;i<<=1)//列舉需要合併的長度 合併後的長度就變成i*2了,所以無需列舉至len
{
Complex wn(cos(PI/i),sin(PI*op/i));//無需乘2,因為合併後的長度i*2,用到的單位複數根只有i
for(int k=0,t=(i<<1);k<len;k+=t)//被分成了l/(i<<1)段序列
{
Complex w(1,0);//注意一點,w是for迴圈執行完畢之後才累乘,因為我們還有我們還有w^0
for(int j=0;j<i;j++,w*=wn)//列舉前半部分,後半部分加上一個i就可以了
{
Complex t=w*a[k+j+i];//k+j+i是後半部分
Complex u=a[k+j];//k+j是前半部分
a[k+j]=u+t;
a[k+j+i]=u-t;
}
}
}
if(op==-1) for(int i=0;i<len;i++) a[i].r/=len,a[i].i/=len;//IFFT 每個數都要/len
}
int main()
{
int n,m,L,i,x;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)scanf("%lf",&a[i]);
for(int i=0;i<=m;i++) scanf("%lf",&b[i]);
m+=n;
for(n=1,L=0;n<=m;n<<=1) L++; //把串變為2的冪次方
for(i=0,x=L-1;i<n;i++) r[i]=(r[i>>1]>>1) |((i&1)<<x);
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=0;i<=m;i++) printf("%d ",int(a[i].r+0.5));
return 0;
}