GDKOI 2021 提高组 Day2 第一题 游戏(解方程)
GDKOI 2021 提高组 Day2 第一题 游戏
题目大意
- 从 0 0 0颗星开始到 n n n颗星结束,有 i i i颗星时,会有 x i x_i xi的概率升星, 1 − x i 1-x_i 1−xi概率降星, i i i为 0 0 0时则保持不变,求到达 n n n颗星的期望步数。
- n ≤ 1 0 6 n\le10^6 n≤106
题解
- 根据期望的线性性,可以分别求出每个从 i i i到 i + 1 i+1 i+1的期望步数,然后全部相加即为答案。
- 当 i = 0 i=0 i=0时,可以列出方程:
- p 0 = x + ( 1 − x ) ( 1 + p 0 ) p_0=x+(1-x)(1+p_0) p0=x+(1−x)(1+p0)。
- 当 i > 0 i>0 i>0时,可以列出方程:
- p i = x + ( 1 − x ) ( 1 + p i − 1 + p i ) p_i=x+(1-x)(1+p_{i-1}+p_i) pi=x+(1−x)(1+pi−1+pi)。
- 发现该形式可以从 0 0 0开始依次解出来。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define md 998244353
#define N 1000010
int read() {
int s = 0;
char x = getchar();
while(x < '0' || x > '9') x = getchar();
while(x >= '0' && x <= '9') s = s * 10 + x - 48, x = getchar();
return s;
}
ll ksm(ll x, ll y) {
if(!y) return 1;
ll l = ksm(x, y / 2);
if(y % 2) return l * l % md * x % md;
return l * l % md;
}
int main() {
int n = read(), i;
ll ans = 0, la = 0;
for(i = 1; i <= n; i++) {
ll x = read(), y = read();
x = x * ksm(y, md - 2) % md;
la = (la + 1 - x * la % md + md) * ksm(x, md - 2) % md;
ans = (ans + la) % md;
}
printf("%lld\n", ans);
return 0;
}
自我小结
- 期望题解方程是比较一般的套路。
- 但尽管再简单的题也要注意检查,注意模数的大小,并且注意每个地方都要记得取模,负数需改为正。
哈哈哈哈哈哈哈哈哈哈