洛谷P4721 【模板】分治 FFT(分治FFT)
多项式求逆的解法看这里
我们考虑用分治
假设现在已经求出了$[l,mid]$的答案,要计算他们对$[mid+1,r]$的答案的影响
那么对右边部分的点$f_x$的影响就是$f_x+=\sum_{i=l}^{mid}f[i]g[x-i]$
发现右边那个东西可以用卷积快速计算
那么只要一边分治一边跑FFT统计贡献就行了
说是分治FFT实际上代码里写的是NTT……
而且分治FFT跑得好慢多项式求逆的速度是它的10倍啊……
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 #define swap(x,y) (x^=y,y^=x,x^=y) 7 #define mul(x,y) (1ll*x*y%P) 8 #define add(x,y) (x+y>=P?x+y-P:x+y) 9 #define dec(x,y) (x-y<0?x-y+P:x-y) 10 using namespace std; 11 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 12 char buf[1<<21],*p1=buf,*p2=buf; 13 inline int read(){ 14 #define num ch-'0' 15 char ch;bool flag=0;int res; 16 while(!isdigit(ch=getc())) 17 (ch=='-')&&(flag=true); 18 for(res=num;isdigit(ch=getc());res=res*10+num); 19 (flag)&&(res=-res); 20 #undef num 21 return res; 22 } 23 char sr[1<<21],z[20];int C=-1,Z; 24 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 25 inline void print(int x){ 26 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 27 while(z[++Z]=x%10+48,x/=10); 28 while(sr[++C]=z[Z],--Z);sr[++C]=' '; 29 } 30 const int N=400005,P=998244353; 31 inline int ksm(int a,int b){ 32 int res=1; 33 while(b){ 34 if(b&1) res=mul(res,a); 35 a=mul(a,a),b>>=1; 36 } 37 return res; 38 } 39 int n,r[N],g[N],f[N],A[N],B[N],O[N],limit,l; 40 inline void init(int len){ 41 limit=1,l=0; 42 while(limit<len*2) limit<<=1,++l; 43 for(int i=0;i<limit;++i) 44 r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); 45 } 46 void NTT(int *A,int type){ 47 for(int i=0;i<limit;++i) 48 if(i<r[i]) swap(A[i],A[r[i]]); 49 for(int mid=1;mid<limit;mid<<=1){ 50 int R=mid<<1,Wn=ksm(3,(P-1)/R);O[0]=1; 51 for(int j=1;j<mid;++j) O[j]=mul(O[j-1],Wn); 52 for(int j=0;j<limit;j+=R){ 53 for(int k=0;k<mid;++k){ 54 int x=A[j+k],y=mul(O[k],A[j+k+mid]); 55 A[j+k]=add(x,y),A[j+k+mid]=dec(x,y); 56 } 57 } 58 } 59 if(type==-1){ 60 reverse(A+1,A+limit); 61 for(int i=0,inv=ksm(limit,P-2);i<limit;++i) 62 A[i]=mul(A[i],inv); 63 } 64 } 65 void CDQ(int *a,int *b,int l,int r){ 66 if(l==r) return; 67 int mid=(l+r)>>1;CDQ(a,b,l,mid); 68 init(r-l+1); 69 for(int i=0;i<limit;++i) A[i]=B[i]=0; 70 for(int i=l;i<=mid;++i) A[i-l]=a[i]; 71 for(int i=0;i<=r-l;++i) B[i]=b[i]; 72 NTT(A,1),NTT(B,1); 73 for(int i=0;i<limit;++i) A[i]=mul(A[i],B[i]); 74 NTT(A,-1); 75 for(int i=mid+1;i<=r;++i) a[i]=add(a[i],A[i-l]); 76 CDQ(a,b,mid+1,r); 77 } 78 int main(){ 79 // freopen("testdata.in","r",stdin); 80 n=read(); 81 for(int i=1;i<n;++i) g[i]=read();f[0]=1; 82 CDQ(f,g,0,n-1); 83 for(int i=0;i<n;++i) print(f[i]); 84 Ot(); 85 return 0; 86 }
深深地明白自己的弱小