Codeforces Global Round 10 H. ZS Shuffles Cards
设f[i]表示还有i个数不在集合内的期望步数,尝试列一下转移式,会发现式子由转移到下一轮的期望步数
和之后的DP值
组成,考虑DP的转移过程,就会发现答案为转移到下一轮的期望步数
期望的轮数
(即把前者设为1之后的DP值)。
前者是易求的,考虑后者,如果直接考虑一轮第一次遇到0时,前面有几个有效数,是很难以优化的(转移到的状态不同)。
法一:DP
换一个角度,仅考虑这轮的第一张牌是什么:但如果分三种情况考虑,肯定转移不到相同的状态;但发现已经出现过的牌是没有意义的,所以直接略过,那么只考虑没出现的牌和0。如果是0,那么直接跳到下一轮,转移到;如果是没出现过的牌,那么在【不考虑已经出现过的牌】的情况下,相当于转移到!(因为在考虑下一张牌的时候,两者的概率都是符合的!)值得注意的是,初始值,因为这相当于刚取完最后一种牌,还需要遇到一个0来增加一轮。
其实从取牌的过程来看,就相当于考虑下一张牌是0或者没出现过的牌的概率。遇到0的时候轮数+1,否则状态+1,而目前的状态又恰好能退出下一张牌的概率!
法二:min-max容斥
直接放图了,,精髓也在于最后一个等式:直接考虑对于一轮,第一个0之前都不出现关键数字的概率比较抽象;但只要忽略掉非0非关键数,就等价于考虑第一个数是否为0!
做了这题后,发现自己已经完全不会数数了【悲】
#include<bits/stdc++.h>
using namespace std;
const int N=4e6+5,P=998244353;
int fpw(int a,int x){
int s=1;
for(;x;x>>=1,a=1ll*a*a%P) if(x&1) s=1ll*s*a%P;
return s;
}
void A(int& x,int y){
x+=y;
if(x>=P) x-=P;
}
int n,m,iv[N],s1,s2,t;
int main()
{
cin>>n>>m;
s1=t=1;
for(int i=1;i<=n+m;i++) iv[i]=fpw(i,P-2);
for(int i=1;i<=n;i++){
t=1ll*t*iv[n+m-i+1]%P*(n-i+1)%P;
A(s1,t);
}
for(int i=1;i<=n;i++) A(s2,iv[i]);
s2=(1ll*s2*m+1)%P;
cout<<1ll*s1*s2%P<<endl;
return 0;
}
分类:
XCPC——计数(组合,多项式)
, XCPC——动态规划
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】