【牛客小白月赛16】I. 石头剪刀布
题意:
在一维直线上,\(A\)和\(B\)玩游戏,\(A\)刚开始在\(1\),他和\(B\)进行剪刀石头布:
- 如果赢了,就往前走一格,赢得概率的\(a\),(如果在\(n\)就不走)
- 如果平局,就不动,平局的概率为\(b\)
- 如果输了,就往后退一格,输的概率为\(1 - a - b\)(如果在\(1\)就不退)
问\(A\)走到\(n\)的期望局数。
思路:
考虑\(f[i]\)表示从\(i\)走到\(n\)的期望步数,那么有:
\[\begin{eqnarray*}
f[i] =
\left\{
\begin{array}{cccc}
Af[i + 1] + (1 - A)f[i] + 1 && i = 1\\
Af[i + 1] + Bf[i] + (1 - A - B)f[i - 1] && 1 < i < n \\
0 && i = n
\end{array}
\right.
\end{eqnarray*}
\]
高斯消元即可。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 110
int n; ll A, B;
const ll p = 1e9 + 7;
ll a[N][N], x[N];
ll gcd(ll a, ll b) {
return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
ll inv(ll a, ll p) {
if (a == 1) return 1;
return inv(p % a, p) * (p - p / a) % p;
}
int Gauss(int equ, int var) {
int max_r, col, k;
for (k = 0, col = 0; k < equ && col < var; ++k, ++col) {
max_r = k;
for (int i = k + 1; i < equ; ++i) {
if (abs(a[i][col]) > abs(a[max_r][col])) {
max_r = i;
}
}
if (a[max_r][col] == 0) {
--k;
continue;
}
if (max_r != k) {
for (int j = col; j < var + 1; ++j) {
swap(a[k][j], a[max_r][j]);
}
}
for (int i = k + 1; i < equ; ++i) {
if (a[i][col] != 0) {
ll LCM = lcm(abs(a[i][col]), abs(a[k][col]));
ll ta = LCM / abs(a[i][col]);
ll tb = LCM / abs(a[k][col]);
if (a[i][col] * a[k][col] < 0) tb = -tb;
for (int j = col; j < var + 1; ++j) {
a[i][j] = ((a[i][j] * ta - a[k][j] * tb) % p + p) % p;
}
}
}
}
for (int i = k; i < equ; ++i) {
if (a[i][col] != 0) {
return -1;
}
}
if (k < var) return var - k;
for (int i = var - 1; i >= 0; --i) {
ll tmp = a[i][var];
for (int j = i + 1; j < var; ++j) {
if (a[i][j] != 0) {
tmp -= a[i][j] * x[j];
tmp = (tmp % p + p) % p;
}
}
x[i] = (tmp * inv(a[i][i], p)) % p;
}
return 0;
}
int main() {
while (scanf("%d%lld%lld", &n, &A, &B) != EOF) {
memset(a, 0, sizeof a);
a[0][0] = p - A; a[0][1] = A;
a[0][n] = -1;
for (int i = 2; i < n; ++i) {
a[i - 1][i - 2] = (1 - A - B + 2ll * p) % p;
a[i - 1][i - 1] = (B - 1 + p) % p;
a[i - 1][i] = A;
a[i - 1][n] = -1;
}
a[n - 1][n - 1] = 1;
Gauss(n, n);
printf("%lld\n", x[0]);
}
return 0;
}

浙公网安备 33010602011771号