题目
牌堆上有n+m(n<=2e6,m<=2e6)张牌,n张是1到n的数字牌,m张是王牌,
初始时,n+m张牌被随机打乱放到牌堆上,主人公有一个初始为空的S集合,
每一秒,主人公都从牌堆顶抽一张牌,
(1)如果是数字牌,就会把这个数放到S集合中去,并把这张牌移除
(2)如果是王牌,
①如果S集合此时已经包含n个数,游戏结束
②否则, 把所有牌都放回牌堆,注意S集合内已放入的数保持不变,
再把n+m张牌随机打乱形成新的牌堆,继续抽取,打乱不计时间
问最后游戏结束的期望时间
思路来源
codeforces comment
https://www.cnblogs.com/Hs-black/p/13518909.html
https://www.cnblogs.com/st1vdy/p/13518667.html#4662181
题解
首先,证一波独立,证明看不懂,直接抄过来
E(ans)=E(每一轮迭代的秒数)*E(迭代的轮数),称每一次抽到王牌为一次迭代
根据期望线性性,
E(每一轮迭代的秒数)
=E(每一张数字牌在所有王牌的左边)+1
=E(1在所有王牌左边)+E(2在所有王牌左边)+...+王牌产生的1秒贡献
=,1/(m+1)是只考虑这张数字牌和m张王牌
接下来求E(迭代的轮数),记f(i)为还有i个数没搞到S里去时,到游戏结束时迭代轮数的期望
则对于f(1)来说,每次都是1/(m+1)的机会能搞进去,搞不进去就会一直重复,几何分布,期望为m+1
而对于f(i)来说,i/(m+i)概率搞到一张数字牌转移到f(i-1),m/(m+i)搞到王牌浪费了一轮还需要f(i)轮,
,化简一下
二者相乘即可,第一部分不用期望线性性的做法是O(n)的,
可参考https://www.cnblogs.com/st1vdy/p/13518667.html#4662181
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int modpow(int x,int n,int mod){
int res=1;
for(;n;n>>=1,x=1ll*x*x%mod)
if(n&1)res=1ll*res*x%mod;
return res;
}
int inv(int x){
return modpow(x,mod-2,mod);
}
int n,m,ans,sum;
int main(){
scanf("%d%d",&n,&m);
ans=(1ll*n*inv(m+1)+1)%mod;
for(int i=1;i<=n;++i){
sum=(sum+inv(i))%mod;
}
sum=(1ll*sum*m+1)%mod;
printf("%d\n",1ll*ans*sum%mod);
return 0;
}