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;

	
}
posted @ 2024-09-23 23:24  xde_yt  阅读(85)  评论(0编辑  收藏  举报