游戏
游戏
题意简述
从 0 星开始,目标达到 n 星。每局游戏:
- 若当前为 i 星(0 ≤ i < n),获胜概率为 \(p_i = \dfrac{x_i}{y_i}\)(以模 \(998244353\) 意义下给出)。
- 胜利:星数 +1
- 失败:星数 -1,但如果当前为 0 星则不减少。
求期望对局次数,答案对 \(998244353\) 取模。
数学推导
设 \(E[i]\) 表示从 \(i\) 颗星出发,到达 \(n\) 颗星的期望对局数。
显然有边界条件:
\(E[n] = 0\)
对于 \(0 \le i < n\),考虑一步转移。
情况 \(i = 0\)
此时失败不减少星数,因此:
\[E[0] = 1 + p_0 \cdot E[1] + (1 - p_0) \cdot E[0]
\]
移项:
\[p_0 \cdot (E[0] - E[1]) = 1
\]
所以:
\[E[1] = E[0] - \frac{1}{p_0}
\]
情况 \(1 \le i < n\)
\[E[i] = 1 + p_i \cdot E[i+1] + (1 - p_i) \cdot E[i-1]
\]
整理得到递推式:
\[E[i+1] = E[i-1] + \frac{1}{p_i} \cdot (E[i] - E[i-1] - 1)
\]
化为线性表示
令 \(E[i] = A[i] \cdot E[0] + B[i]\),其中 \(A[i], B[i]\) 是模 \(MOD\) 下的系数。
初始:
- \(i = 0\):
\(A[0] = 1\),\(B[0] = 0\) - \(i = 1\):
\(A[1] = 1\),\(B[1] = -\dfrac{1}{p_0}\)
对于 \(i \ge 2\),设 \(p = p_{i-1}\)(即从 \(i-1\) 星获胜的概率),由递推式:
\[E[i] = E[i-2] + \frac{1}{p} \cdot (E[i-1] - E[i-2] - 1)
= \left(1 - \frac{1}{p}\right) \cdot E[i-2] + \frac{1}{p} \cdot E[i-1] - \frac{1}{p}
\]
因此系数递推:
\[A[i] = \frac{1}{p} \cdot A[i-1] + \left(1 - \frac{1}{p}\right) \cdot A[i-2]
\]
\[B[i] = \frac{1}{p} \cdot B[i-1] + \left(1 - \frac{1}{p}\right) \cdot B[i-2] - \frac{1}{p}
\]
其中 \(\frac{1}{p}\) 在模意义下即为 \(y_{i-1} \cdot \operatorname{inv}(x_{i-1})\)。
最终,因为 \(E[n] = 0\),有:
\[A[n] \cdot E[0] + B[n] = 0
\Rightarrow E[0] = -\frac{B[n]}{A[n]} \pmod{MOD}
\]
所以答案即为 \(E[0]\)。
算法流程
- 读入 \(n\),以及 \(n\) 组 \((x_i, y_i)\)(\(i = 0 \dots n-1\))。
- 预处理 \(1/p_0\) 并初始化 \(A[0], B[0], A[1], B[1]\)。
- 从 \(i = 2\) 到 \(n\) 循环:
- 计算 \(p = \dfrac{x_{i-1}}{y_{i-1}}\),得到 \(\operatorname{inv}p = y_{i-1} \cdot \operatorname{inv}(x_{i-1})\)。
- 令 \(c_1 = \operatorname{inv}p\),\(c_2 = 1 - \operatorname{inv}p\)。
- \(A[i] = c_1 \cdot A[i-1] + c_2 \cdot A[i-2]\)
- \(B[i] = c_1 \cdot B[i-1] + c_2 \cdot B[i-2] - \operatorname{inv}p\)
- 计算 \(\text{ans} = -B[n] \cdot \operatorname{inv}(A[n]) \pmod{MOD}\)。
- 输出 \(\text{ans}\)。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;
struct wait {
ll k;
ll num;
};
ll modpow(ll a, ll b) {
ll r = 1;
while(b) {
if(b&1) r = r * a % MOD;
a = a*a%MOD;
b >>= 1;
}
return r;
}
void solve() {
int n; cin >> n;
vector<ll> x(n + 1, 0), y(n + 1, 0);
for(int i = 0; i < n; i ++) cin >> x[i] >> y[i];
vector<wait> dp(n + 1);
dp[0].k = 1, dp[0].num = 0;
ll p0_ = y[0] * modpow(x[0], MOD-2) % MOD;;
dp[1].k = 1, dp[1].num = (-p0_ + MOD)%MOD;
for(int i = 2; i <= n; i ++) {
ll tx = x[i-1], ty = y[i-1];
ll pi1 = tx * modpow(ty, MOD-2) % MOD; pi1 = (pi1 - 1 + MOD) % MOD;
ll pi_q = ty * modpow(tx, MOD-2) % MOD;
dp[i].k = (dp[i-1].k + pi1*dp[i-2].k % MOD + MOD) % MOD * pi_q % MOD;
dp[i].num = (dp[i-1].num + pi1*dp[i-2].num % MOD - 1 + MOD) % MOD * pi_q % MOD;
}
ll qw = modpow(dp[n].k, MOD-2);
ll ans = -dp[n].num * qw % MOD;
if(ans < 0) ans += MOD;
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int _=1; //cin >> _;
while(_--) solve();
return 0;
}

浙公网安备 33010602011771号