@xiaoziyao
2021-04-03T07:09:47.000000Z
字数 3497
阅读 1463
解题报告
张牌,有一张是王牌,打乱次,设有次第一次为王牌,求的期望。()
死亡推式子题。。。刚好可以总结一些推式子题套路。
设,那么首先很容易列出式子:
枚举王牌出现次数,然后不难得到这个式子。
但这个和式的上界是,怎么优化枚举都没有办法,所以套路地用第二类斯特林数展开,然后交换求和式(组合意义就是个球放到个盒子里):
利用这个式子:
然后利用一个结论(下方有说明)继续推:
这个结论很常见:
利用上面提到的第二类斯特林数通项暴力展开,再次交换求和式:
对上面展开幂次的式子二项式反演得:
设,那么原式就变成可以递推的式子了:
那么我们现在就要求出,很容易知道时。
考虑倒序递推,直接暴力展开组合数:
那么我们随便筛一下,然后拆一下组合数,就可以线性递推出来了。
谨慎起见,可以特判一下的情况。
#include<stdio.h>const int maxk=10000005,mod=998244353;int n,m,k,p,cnt,ans,mul;int pw[maxk],c[maxk],P[maxk],inv[maxk],S[maxk],pmul[maxk],npmul[maxk],fmul[2];int ksm(int a,int b){int res=1;while(b){if(b&1)res=1ll*res*a%mod;a=1ll*a*a%mod,b>>=1;}return res;}void sieve(int n){fmul[0]=1,fmul[1]=mod-1;inv[1]=c[1]=pw[1]=1;for(int i=2;i<=n;i++){inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;if(c[i]==0)P[++cnt]=i,pw[i]=ksm(i,k);for(int j=1;j<=cnt;j++){if(i*P[j]>n)break;c[i*P[j]]=1,pw[i*P[j]]=1ll*pw[i]*pw[P[j]]%mod;if(i%P[j]==0)break;}}pmul[0]=npmul[0]=1;for(int i=1;i<=n;i++)pmul[i]=1ll*pmul[i-1]*p%mod,npmul[i]=1ll*npmul[i-1]*(1-p+mod)%mod;}int main(){scanf("%d%d%d",&n,&m,&k),p=ksm(m,mod-2);sieve(k);if(n<k){mul=1;//C(n,0)for(int i=0;i<=n;i++){ans=(ans+1ll*mul*pmul[i]%mod*npmul[n-i]%mod*pw[i]%mod)%mod;mul=1ll*mul*inv[i+1]%mod*(n-i)%mod;//C(n,i)->C(n,i+1)}printf("%d\n",ans);return 0;}S[k]=1;mul=n-k;//C(n-k,1)for(int i=k-1;i>=0;i--){S[i]=(1ll*(1-p+mod)*S[i+1]%mod+1ll*mul*fmul[(k-i)&1]%mod*pmul[k-i]%mod)%mod;mul=1ll*mul*inv[k-i+1]%mod*(n-i)%mod;//C(n-i-1,k-i)->C(n-i,k-i+1)}mul=1;//C(n,0)for(int i=0;i<=k;i++){ans=(ans+1ll*pmul[i]*pw[i]%mod*mul%mod*S[i]%mod)%mod;mul=1ll*mul*inv[i+1]%mod*(n-i)%mod;//C(n,i)-C(n,i+1)}printf("%d\n",ans);return 0;}
