不公平对局
不公平的对局
小红执黑先手,每回合依次进行:
- 小红以概率
p1 = a1/b1吃掉小紫一枚棋子; - 小紫以概率
p2 = a2/b2吃掉小红一枚棋子。
任何一方累计吃子数达到 x 即判负。求小红最终获胜的概率,对 MOD = 1e9+7 取模输出。
输入:x,a1 b1,a2 b2(保证 a1,a2 不同时为 0)
输出:模意义下的答案分数。
状态定义
设 dp[i][j] 表示当前小红已吃 i 枚、小紫已吃 j 枚,且均未达到 x 时,小红最终获胜的概率。
边界条件
dp[x][j] = 0(小红先达到 x,输)dp[i][x] = 1(小紫先达到 x,小红赢)
转移方程
设:
- 小红吃子概率
p1,不吃q1 = 1 - p1 - 小紫吃子概率
p2,不吃q2 = 1 - p2
一回合四种情况:
| 小红 | 小紫 | 概率 | 下一状态 |
|---|---|---|---|
| 吃 | 吃 | p1*p2 | dp[i+1][j+1] |
| 吃 | 不吃 | p1*q2 | dp[i+1][j] |
| 不吃 | 吃 | q1*p2 | dp[i][j+1] |
| 不吃 | 不吃 | q1*q2 | dp[i][j](自环) |
移项得:
dp[i][j] = ( p1*p2*dp[i+1][j+1] + p1*q2*dp[i+1][j] + q1*p2*dp[i][j+1] ) / (1 - q1*q2)
分母 D = 1 - q1*q2 = p1 + p2 - p1*p2,保证非零。
计算顺序
由于依赖 i+1 和同一行 j+1,采用倒序枚举:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1e9 + 7;
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 x; cin >> x;
ll a, b, c, d; cin >> a >> b >> c >> d;
ll p1 = modpow(b, MOD - 2) * a % MOD, p2 = modpow(d, MOD - 2) * c % MOD;
ll q1 = (1 - p1 + MOD) % MOD, q2 = (1 - p2 + MOD) % MOD;
ll y = (1 - q1 * q2 % MOD + MOD) % MOD;
y = modpow(y, MOD - 2);
vector<vector<ll>> dp(x + 1, vector<ll>(x + 1, 0));
for(int i = 0; i < x; i ++) dp[i][x] = 1;
for(int i = x - 1; i >= 0; i --) for(int j = x - 1; j >= 0; j --) {
ll w1 = dp[i][j + 1] * q1 % MOD * p2 % MOD;
ll w2 = dp[i + 1][j] * p1 % MOD * q2 % MOD;
ll w3 = dp[i + 1][j + 1] * p1 % MOD * p2 % MOD;
dp[i][j] = (w1 + w2 + w3) % MOD * y % MOD;;
}
cout << dp[0][0] << "\n";
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int _ = 1; //cin >> _;
while(_ --) solve();
return 0;
}

浙公网安备 33010602011771号