洛谷 P3803 多項式乘法
阿新 • • 發佈:2018-01-24
背景 給定 add n+1 esp clas 題目 -h adg
題目背景
這是一道FFT模板題
題目描述
給定一個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)的系數。
輸入輸出樣例
輸入樣例#1:1 2 1 2 1 2 1輸出樣例#1:
1 4 5 2
說明
保證輸入中的系數大於等於 0 且小於等於9。
對於100%的數據: n, m \leq {10}^6n,m≤106, 共計20個數據點,2s。
數據有一定梯度。
空間限制:256MB
NTT和FFT有驚人的類似度hhh,總的說就是把單位根換成了原根。
最好是取一個形如p=k*2^x+1這樣的質數p,這裏x最好大一點。
然後在FFT裏1的K次單位根是(cos(2*π/K),sin(2*π/K)) (一個復數),而NTT裏則是 g^((p-1)/K)。
dft的逆函數的話也類似,就是把g換成g^-1。
#include<bits/stdc++.h> #define ll long long #define maxn 3000005 #define ha 998244353 using namespace std; const intba=3; const int ni=ha/ba+1; inline int add(int x,int y){ x+=y; if(x>=ha) x-=ha; return x; } inline int dec(int x,int y){ x-=y; if(x<0) x+=ha; return x; } inline int ksm(int x,int y){ int an=1; for(;y;y>>=1,x=(ll)x*x%ha) if(y&1) an=(ll)an*x%ha; returnan; } int n,m,a[maxn],b[maxn]; int r[maxn],l,inv; inline void fft(int *c,int f){ for(int i=0;i<n;i++) if(i<r[i]) swap(c[i],c[r[i]]); for(int i=1;i<n;i<<=1){ int omega=(f==1?ksm(ba,(ha-1)/(i<<1)):ksm(ni,(ha-1)/(i<<1))); for(int j=0,p=i<<1;j<n;j+=p){ int now=1; for(int k=0;k<i;k++,now=(ll)now*omega%ha){ int x=c[j+k],y=(ll)now*c[j+k+i]%ha; c[j+k]=add(x,y); c[j+k+i]=dec(x,y); } } } if(f==-1) for(int i=0;i<n;i++) c[i]=(ll)c[i]*inv%ha; } int main(){ scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) scanf("%d",a+i); for(int i=0;i<=m;i++) scanf("%d",b+i); m+=n; for(n=1,l=0;n<=m;n<<=1) l++; for(int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); inv=ksm(n,ha-2); fft(a,1),fft(b,1); for(int i=0;i<n;i++) a[i]=(ll)a[i]*b[i]%ha; fft(a,-1); for(int i=0;i<=m;i++) printf("%d ",a[i]); puts(""); return 0; }
洛谷 P3803 多項式乘法