[luogu5162]WD与积木
设$g_{n}$表示$n$个积木放的方案数,枚举最后一层所放的积木,则有$g_{n}=\sum_{i=1}^{n}c(n,i)g_{n-i}$(因为积木有编号的所以要选出$i$个)
将组合数展开并化简,得到$\frac{g_{n}}{n!}=\sum_{i=1}^{n}\frac{g_{n-i}}{i!(n-i)!}$,明显是一个分治fft的形式,转换为多项式求逆:
令$g_{n}$的指数生成函数为$G(x)=\sum_{i=0}^{\infty}\frac{g_{i}}{i!}x^{i}$,再令$H(x)=\sum_{i=0}^{\infty}\frac{x^{i}}{i!}$,考虑$H(x)G(x)$,代入并将$i=0$和$j=0$提出可得$H(x)G(x)=\sum_{i=0}^{\infty}(\sum_{j=0}^{i}H(x)[j]\cdot G(x)[i-j])x^{i}=2G(x)-1$,即$G(x)=\frac{1}{2-H(x)}$
设$f_{n}$表示$n$个积木放的方案数的层数之和,那么根据期望的定义,答案$E=\frac{f_{n}}{g_{n}}$
类似的,可以写出$f_{n}$的递推式,即$f_{n}=g_{n}+\sum_{i=1}^{n}c(n,i)f_{n-i}$($g_{n}$是因为每一个方案都要+1),将$g_{n}$的表达式展开,有$\frac{f_{n}}{n!}=\sum_{i=1}^{n}\frac{f_{n-i}+g_{n-i}}{i!(n-i)!}$,同样去转换为多项式求逆:
令$f_{n}$的指数生成函数为$F(x)=\sum_{i=0}^{\infty}\frac{f_{i}}{i!}x^{i}$,$H(x)$和$G(x)$相同,考虑$H(x)(G(x)+F(x))$,类似上面可得$H(x)(G(x)+F(x))=G(x)+2F(x)$(注意$f_{0}=0$),即$F(x)=\frac{(H(x)-1)G(x)}{2-H(x)}=(H(x)-1)G(x)^{2}$
最终答案即$\frac{F(x)[n]}{G(x)[n]}$(都除以了$n!$),注意最后一步不能将$\frac{F(x)}{G(x)}$作为结果,因为这不等于答案
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N (1<<18) 4 #define mod 998244353 5 int t,n,a[N],c[N],h[N],g[N],f[N]; 6 int ksm(int n,int m){ 7 if (!m)return 1; 8 int s=ksm(n,m>>1); 9 s=1LL*s*s%mod; 10 if (m&1)s=1LL*s*n%mod; 11 return s; 12 } 13 void ntt(int *a,int n,int p){ 14 for(int i=0;i<(1<<n);i++){ 15 int rev=0; 16 for(int j=0;j<n;j++)rev=rev*2+((i&(1<<j))>0); 17 if (i<rev)swap(a[i],a[rev]); 18 } 19 for(int i=2;i<=(1<<n);i*=2){ 20 int s=ksm(3,(mod-1)/i); 21 if (p)s=ksm(s,mod-2); 22 for(int j=0;j<(1<<n);j+=i) 23 for(int k=0,ss=1;k<(i>>1);k++,ss=1LL*ss*s%mod){ 24 int x=a[j+k],y=1LL*a[j+k+(i>>1)]*ss%mod; 25 a[j+k]=(x+y)%mod; 26 a[j+k+(i>>1)]=(x+mod-y)%mod; 27 } 28 } 29 if (p){ 30 int s=ksm((1<<n),mod-2); 31 for(int i=0;i<(1<<n);i++)a[i]=1LL*a[i]*s%mod; 32 } 33 } 34 void Inv(int *a,int *b,int n){ 35 if (!n){ 36 b[0]=ksm(a[0],mod-2); 37 return; 38 } 39 Inv(a,b,n-1); 40 for(int i=0;i<(1<<n);i++)c[i]=a[i]; 41 for(int i=(1<<n);i<(1<<n+1);i++)c[i]=0; 42 ntt(c,n+1,0); 43 ntt(b,n+1,0); 44 for(int i=0;i<(1<<n+1);i++)b[i]=1LL*b[i]*(mod+2-1LL*c[i]*b[i]%mod)%mod; 45 ntt(b,n+1,1); 46 for(int i=(1<<n);i<(1<<n+1);i++)b[i]=0; 47 } 48 int main(){ 49 a[0]=1; 50 for(int i=1;i<N;i++)a[i]=1LL*a[i-1]*ksm(i,mod-2)%mod; 51 h[0]=(mod+2-a[0])%mod; 52 for(int i=1;i<N/2;i++)h[i]=(mod-a[i])%mod; 53 Inv(h,g,17); 54 memcpy(f,g,sizeof(g)); 55 ntt(f,18,0); 56 for(int i=0;i<N;i++)f[i]=1LL*f[i]*f[i]%mod; 57 ntt(f,18,1); 58 for(int i=N/2;i<N;i++)f[i]=0; 59 ntt(f,18,0); 60 h[0]=0; 61 for(int i=1;i<N/2;i++)h[i]=a[i]; 62 ntt(h,18,0); 63 for(int i=0;i<N;i++)f[i]=1LL*f[i]*h[i]%mod; 64 ntt(f,18,1); 65 scanf("%d",&t); 66 while (t--){ 67 scanf("%d",&n); 68 printf("%lld\n",1LL*f[n]*ksm(g[n],mod-2)%mod); 69 } 70 }