CF1392H ZS Shuffles Cards 题解
题目描述
有 \(n+m\) 张牌,其中 \(n\) 张标有数字 \(1,\cdots,n\) ,另外 \(m\) 张为鬼牌,初始随机打乱。
每轮你可以抽一张牌:
-
抽到标有数字 \(x\) 的牌:从牌堆中移除这张牌,令 \(x\to S\) 。
-
抽到鬼牌:
如果 \(S=\{1,\cdots,n\}\) ,游戏结束。
否则将 \(n+m\) 张牌随机打乱,重新开始抽牌。
求游戏结束的期望轮数,对 \(998244353\) 取模。
数据范围
- \(1\le n,m\le 2\cdot 10^6\) 。
时间限制 \(\texttt{2s}\) ,空间限制 \(\texttt{512MB}\) 。
分析
\(f_{i,j}\) 表示牌堆中有 \(i\) 张未抽到的牌和 \(j\) 张已抽到的牌(都不算鬼牌),到达游戏结束的期望步数。
目标求出 \(f_{n,0}\) , \(f_{i,j}\) 有三种转移:
- 抽到一张未抽到的牌:转移到 \(f_{i-1,j}\) ,概率为 \(\frac i{i+j+m}\) 。
- 抽到一张已抽到的牌:转移到 \(f_{i,j-1}\),概率为 \(\frac j{i+j+m}\) 。
- 抽到鬼牌:转移到 \(f_{i,n-i}\) ,概率为 \(\frac m{i+j+m}\) 。
直接转移显然有后效性,考虑解方程。
先考虑 \(i=0\) 的情况,此时抽到鬼牌意味着游戏结束:
手玩一下就会发现:
对于 \(i\neq 0\) 的情况,转移方程为:
令 \(j\gets j+1\) :
\((i+j+m+1)\times(2)-(i+j+m)\times(1)\):
令 \(g_{i,j}=f_{i,j+1}-f_{i,j}\) :
注意到递推边界 \(g_{0,j}=\frac 1{m+1}\) ,因此 \(\forall i+j\le n\) ,均满足 \(g_{i,j}=\frac 1{m+1}\) 。
在 \((1)\) 中令 \(j=n-i\) :
将 \(f_{i-1,n-i}\) 替换成 \(f_{i-1,n-i+1}\) ,将 \(f_{i,n-i-1}\) 替换成 \(f_{i,n-i}\) :
结合初始值 \(f_{0,n}=\frac {n+m+1}{m+1}\) ,可知 \(f_{n,0}=\frac {n+m+1}{m+1}+(n+m-\frac n{m+1})\sum_{i=1}^n\frac 1i\) 。
时间复杂度可以做到 \(\mathcal O(n)\) ,但是快速幂求逆元也能过。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+5,mod=998244353;
int m,n,inv,sum;
inline int qpow(int a,int k)
{
int res=1;
for(;k;a=1ll*a*a%mod,k>>=1) if(k&1) res=1ll*res*a%mod;
return res;
}
int main()
{
scanf("%d%d",&n,&m),inv=qpow(m+1,mod-2);
for(int i=1;i<=n;i++) sum=(sum+qpow(i,mod-2))%mod;
printf("%lld\n",((n+m+1ll)*inv+(n+m-1ll*n*inv%mod+mod)*sum)%mod);
return 0;
}
本文来自博客园,作者:peiwenjun,转载请注明原文链接:https://www.cnblogs.com/peiwenjun/p/17490302.html
浙公网安备 33010602011771号