洛谷P4721 【模板】分治 FFT(生成函数+多项式求逆)
我是用多项式求逆做的因为分治FFT看不懂……
upd:分治FFT的看这里
话说这个万恶的生成函数到底是什么东西……
我们令$F(x)=\sum_{i=0}^\infty f_ix^i,G(x)=\sum_{i=0}^\infty g_ix^i$,且$g_0=0$
这俩玩意儿似乎就是$f(x)$和$g(x)$的生成函数
那么就有$$F(x)G(x)=\sum_{i=0}^\infty x^i\sum_{j+k=i}f_jg_k$$
然后根据题目,有$$f_i=\sum_{j=1}^if_{i-j}g_j$$
然后因为$g_0=0$,所以
$$f_i=\sum_{j+k=i}f_jg_k$$
又因为该式子只有在$i=0$时不成立,于是代入并手算一下$i=0$的时候,可得$$F(x)G(x)=\sum_{i=0}^\infty f_ix^i-f_0x^0$$
又因为$f_0=x^0=1$,可得$$F(x)G(x)=F(x)-1$$
然后我们只要求它的前$n$项就可以了,所以取模$$F(x)G(x)\equiv F(x)-1\pmod{x^n}$$
然后移项$$F(x)\equiv\frac{1}{1-G(x)}\pmod{x^n}$$
$$F(x)\equiv(1-G(x))^{-1}\pmod{x^n}$$
然后去隔壁把多项式求逆的板子抄来就好了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #define swap(x,y) (x^=y,y^=x,x^=y) 6 #define mul(x,y) (1ll*x*y%P) 7 #define add(x,y) (x+y>=P?x+y-P:x+y) 8 #define dec(x,y) (x-y<0?x-y+P:x-y) 9 using namespace std; 10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 11 char buf[1<<21],*p1=buf,*p2=buf; 12 inline int read(){ 13 #define num ch-'0' 14 char ch;bool flag=0;int res; 15 while(!isdigit(ch=getc())) 16 (ch=='-')&&(flag=true); 17 for(res=num;isdigit(ch=getc());res=res*10+num); 18 (flag)&&(res=-res); 19 #undef num 20 return res; 21 } 22 char sr[1<<21],z[20];int C=-1,Z; 23 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 24 inline void print(int x){ 25 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 26 while(z[++Z]=x%10+48,x/=10); 27 while(sr[++C]=z[Z],--Z);sr[++C]=' '; 28 } 29 const int N=400005,P=998244353,G=3; 30 inline int ksm(int a,int b){ 31 int res=1; 32 while(b){ 33 if(b&1) res=mul(res,a); 34 a=mul(a,a),b>>=1; 35 } 36 return res; 37 } 38 int n,r[N],g[N],f[N],A[N],B[N],O[N]; 39 void NTT(int *A,int type,int len){ 40 int limit=1,l=0; 41 while(limit<len) limit<<=1,++l; 42 for(int i=0;i<limit;++i) 43 r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); 44 for(int i=0;i<limit;++i) 45 if(i<r[i]) swap(A[i],A[r[i]]); 46 for(int mid=1;mid<limit;mid<<=1){ 47 int R=mid<<1,Wn=ksm(G,(P-1)/R);O[0]=1; 48 for(int j=1;j<mid;++j) O[j]=mul(O[j-1],Wn); 49 for(int j=0;j<limit;j+=R){ 50 for(int k=0;k<mid;++k){ 51 int x=A[j+k],y=mul(O[k],A[j+k+mid]); 52 A[j+k]=add(x,y),A[j+k+mid]=dec(x,y); 53 } 54 } 55 } 56 if(type==-1){ 57 reverse(A+1,A+limit); 58 for(int i=0,inv=ksm(limit,P-2);i<limit;++i) 59 A[i]=mul(A[i],inv); 60 } 61 } 62 void work(int *a,int *b,int len){ 63 if(len==1) return (void)(b[0]=ksm(a[0],P-2)); 64 work(a,b,len>>1); 65 for(int i=0;i<len;++i) A[i]=a[i],B[i]=b[i]; 66 NTT(A,1,len<<1),NTT(B,1,len<<1); 67 for(int i=0;i<(len<<1);++i) 68 A[i]=mul(mul(A[i],B[i]),B[i]); 69 NTT(A,-1,len<<1); 70 for(int i=0;i<len;++i) b[i]=dec(1ll*b[i]*2%P,A[i]); 71 } 72 int main(){ 73 // freopen("testdata.in","r",stdin); 74 n=read(); 75 for(int i=1;i<n;++i) g[i]=read(); 76 int len;for(len=1;len<n;len<<=1); 77 for(int i=1;i<n;++i) g[i]=P-g[i];g[0]=1; 78 work(g,f,len); 79 for(int i=0;i<n;++i) print(f[i]); 80 Ot(); 81 return 0; 82 }
深深地明白自己的弱小