2024icpc(Ⅱ)网络赛补题 GL
2024icpc(Ⅱ)网络赛补题 GL
题目链接:The 2024 ICPC Asia EC Regionals Online Contest (II)
G、Game
题意:
给定Alice和Bob的每一轮的概率\(p_0, p_1\)
给定Alice和Bob的初始数字\(x,y\)。
对于每一轮:
- 如果Alice获胜,则bob的数字\(y\)需要减去\(x\)。(如果\(y\leq0\),Alice获胜)
- 如果Bob获胜,则Alice的数字\(x\)需要减去\(y\)。(如果\(x\leq0\),Bob获胜)
重复上述游戏,直到出现胜利者。
问,Alice最终能赢得游戏的概率有多大。
思路:
可以直接用减法模拟,用除法加速,类似辗转相除法
当\(x>y\)时,\(x\)可以输\(x/y\)场,转移到\((x\%y,y)\)的状态,其他状态A必胜
当\(x\geq y\)时,\(x\)必须赢\(y/x\)场,转移到\((x,x\%y)\)的状态,然后在考虑A必胜的情况
代码:
const int mod=998244353;
int x,y,a0,a1,b,invb,ans;
int p0,p1;
int quickpow(int x,int y){
int res=1;
while(y){
if(y&1) res=(res*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return res;
}
int inv(int x){
return quickpow(x,mod-2);
}
int add(int x,int y){
return ((x%mod)+(y%mod))%mod;
}
int sub(int x,int y){
return ((x-y)%mod+mod)%mod;
}
int mul(int x,int y){
return (x%mod*y%mod)%mod;
}
int dfs(int x,int y,int p){
if(x == 0) return 0;
if(y == 0) return p;
if(x > y){
int k = x / y;
int cur = quickpow(p1,k);//到达状态(x%y,y)的概率
int res = mul(sub(1,cur),p); //(1-cur)*p => A必胜的概率
res = add(res,dfs(x%y,y,mul(p,cur))); //res+到达状态(x%y,y)A胜的概率
return res;
}else{//x<=y 此时A必须赢下k场到达状态(x,y%x)才可能赢
int k = y / x;
int cur = quickpow(p0,k);
int res = mul(cur,p); //到达状态(x,y%x)的概率
return dfs(x,y%x,res);
}
}
void solve()
{
cin >> x >> y >> a0 >> a1 >> b;
b = a0 + a1;
int invb = inv(b);
p0 = mul(a0,invb);
p1 = mul(a1,invb);
ans = dfs(x,y,1);
cout << ans << endl;
}
L、502 Bad Gateway
题意:
给定一个\(T\),每一步可以做以下两个操作:
1、减1
2、随机重置为\([1,T]\)中的某个整数
求在最优策略下,得到\(0\)的期望步数
思路:
最优策略为选择一个阈值\(S\),如果大于\(S\)的话,就重置;如果小于\(S\)的话就直接减到\(0\)
所以我们可以列出下面这个方程
\[E=\frac{\frac{S\times(1+S)}{2}\times(S+1)\times(T-S)}{T}
\]
可以解得
\[E=\frac{S-1}{2}+\frac{T}{S}=\frac{S}{2}+\frac{T}{S}-\frac{1}{2}
\]
所以能得到期望的最大值在\(S=\sqrt{2T}\)取得
所以在\(\lfloor \sqrt{2T} \rfloor\)和\(\lceil \sqrt{2T}\rceil\)两点取
void solve(){
int t;
cin >> t;
int x1 = (int)sqrt(2*t);
int x2 = min(t,x1+1);
int fz1 = x1*x1 + 2*t - x1;
int fm1 = 2*x1;
int g1 = __gcd(fz1,fm1);
fz1 /= g1;
fm1 /= g1;
int fz2 = x2*x2 + 2*t - x2;
int fm2 = 2*x2;
int g2 = __gcd(fz2,fm2);
fz2 /= g2;
fm2 /= g2;
if(fz1*fm2<=fz2*fm1) cout << fz1 << " " << fm1 << endl;
else cout << fz2 << " " << fm2 << endl;
}