Codeforces Global Round 10 H. ZS Shuffles Cards(期望线性性 几何分布)

探讨了在n+m张牌的牌堆游戏中,通过数学和编程方法计算游戏结束期望时间的问题。游戏规则包括随机抽取数字牌和王牌,以及王牌触发的牌堆重置条件。解析了期望时间的计算公式,提供了详细的解题思路和代码实现。

题目

牌堆上有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秒贡献

=n*\frac{1}{m+1}+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)轮,

f(i)=\frac{i}{m+i}*f(i-1)+\frac{m}{m+i}*(f(i)+1),化简一下f(n)=f(1)+\sum_{i=2}^{n}\frac{m}{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;
}

 

### 关于Codeforces Round 925 (Div. 3) 对于希望参加或回顾Codeforces Round 925 (Div. 3)的比赛者而言,理解该轮次的具体题目及其解析至关重要。然而,在提供的参考资料中并未直接提及关于此特定轮次的信息[^1]。 通常情况下,Codeforces的每一场比赛都包含了不同难度级别的若干问题,旨在测试参赛者的编程技巧以及解决问题的能力。以类似的Div. 3赛事为例,比赛往往设计了适合较低评级选手挑战的任务,鼓励更多新手参与到竞争当中来,并提供了一个良好的平台让这些新人们能够逐步提升自我[^2]。 针对想要深入了解Codeforces Round 925 (Div. 3),建议访问官方Codeforces网站查看具体公告页面获取最准确的比赛详情和官方题解。此外,社区论坛也是寻找非正式讨论和个人见解的好地方,许多经验丰富的参与者会在赛后分享自己对各道试题的看法和技术细节分析[^3]。 为了准备这类竞赛,练习过往相似类型的题目是非常有益的做法之一。例如,在其他几场提到的比赛中所涉及的一些基础概念和技术点可能会重复出现,因此熟悉它们有助于更好地应对未来的考验[^4]。 ```python # 示例代码用于说明如何查找并打印指定范围内的素数, # 这种技能可能在某些算法竞赛题目中有用。 def find_primes(n): primes = [] is_prime = [True] * (n + 1) p = 2 while p ** 2 <= n: if is_prime[p]: for i in range(p**2, n + 1, p): is_prime[i] = False p += 1 for p in range(2, n + 1): if is_prime[p]: primes.append(p) return primes print(find_primes(30)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小衣同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值