[关闭]
@xiaoziyao 2021-04-03T15:09:47.000000Z 字数 3497 阅读 1087

P6031 CF1278F Cards 加强版解题报告

解题报告


P6031 CF1278F Cards 加强版解题报告:

更差的阅读体验

题意

张牌,有一张是王牌,打乱次,设有次第一次为王牌,求的期望。(

分析

死亡推式子题。。。刚好可以总结一些推式子题套路。

,那么首先很容易列出式子:

枚举王牌出现次数,然后不难得到这个式子。

但这个和式的上界是,怎么优化枚举都没有办法,所以套路地用第二类斯特林数展开,然后交换求和式(组合意义就是个球放到个盒子里):

利用这个式子:

然后利用一个结论(下方有说明)继续推:

这个结论很常见:

利用上面提到的第二类斯特林数通项暴力展开,再次交换求和式:

对上面展开幂次的式子二项式反演得:

,那么原式就变成可以递推的式子了:

那么我们现在就要求出,很容易知道

考虑倒序递推,直接暴力展开组合数:

那么我们随便筛一下,然后拆一下组合数,就可以线性递推出来了。

代码

谨慎起见,可以特判一下的情况。

  1. #include<stdio.h>
  2. const int maxk=10000005,mod=998244353;
  3. int n,m,k,p,cnt,ans,mul;
  4. int pw[maxk],c[maxk],P[maxk],inv[maxk],S[maxk],pmul[maxk],npmul[maxk],fmul[2];
  5. int ksm(int a,int b){
  6. int res=1;
  7. while(b){
  8. if(b&1)
  9. res=1ll*res*a%mod;
  10. a=1ll*a*a%mod,b>>=1;
  11. }
  12. return res;
  13. }
  14. void sieve(int n){
  15. fmul[0]=1,fmul[1]=mod-1;
  16. inv[1]=c[1]=pw[1]=1;
  17. for(int i=2;i<=n;i++){
  18. inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
  19. if(c[i]==0)
  20. P[++cnt]=i,pw[i]=ksm(i,k);
  21. for(int j=1;j<=cnt;j++){
  22. if(i*P[j]>n)
  23. break;
  24. c[i*P[j]]=1,pw[i*P[j]]=1ll*pw[i]*pw[P[j]]%mod;
  25. if(i%P[j]==0)
  26. break;
  27. }
  28. }
  29. pmul[0]=npmul[0]=1;
  30. for(int i=1;i<=n;i++)
  31. pmul[i]=1ll*pmul[i-1]*p%mod,npmul[i]=1ll*npmul[i-1]*(1-p+mod)%mod;
  32. }
  33. int main(){
  34. scanf("%d%d%d",&n,&m,&k),p=ksm(m,mod-2);
  35. sieve(k);
  36. if(n<k){
  37. mul=1;//C(n,0)
  38. for(int i=0;i<=n;i++){
  39. ans=(ans+1ll*mul*pmul[i]%mod*npmul[n-i]%mod*pw[i]%mod)%mod;
  40. mul=1ll*mul*inv[i+1]%mod*(n-i)%mod;//C(n,i)->C(n,i+1)
  41. }
  42. printf("%d\n",ans);
  43. return 0;
  44. }
  45. S[k]=1;
  46. mul=n-k;//C(n-k,1)
  47. for(int i=k-1;i>=0;i--){
  48. S[i]=(1ll*(1-p+mod)*S[i+1]%mod+1ll*mul*fmul[(k-i)&1]%mod*pmul[k-i]%mod)%mod;
  49. mul=1ll*mul*inv[k-i+1]%mod*(n-i)%mod;//C(n-i-1,k-i)->C(n-i,k-i+1)
  50. }
  51. mul=1;//C(n,0)
  52. for(int i=0;i<=k;i++){
  53. ans=(ans+1ll*pmul[i]*pw[i]%mod*mul%mod*S[i]%mod)%mod;
  54. mul=1ll*mul*inv[i+1]%mod*(n-i)%mod;//C(n,i)-C(n,i+1)
  55. }
  56. printf("%d\n",ans);
  57. return 0;
  58. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注