1. 程式人生 > >洛谷 P3803 多項式乘法

洛谷 P3803 多項式乘法

背景 給定 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,m106, 共計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 int
ba=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; return
an; } 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 多項式乘法