abcdeffa's Blog

当局者迷,旁观者清。

0%

GMOJ S6965 【游戏】

Description

你现在在第 0 关,胜利可以到下一关,失败则回到上一关。特别地,在第 0 关失败后依然在第 0 关。你在第 $i$ 关胜利的概率为 $p_i$。现在问你过掉 $n$ 关期望需要进行多少次对局。试求答案对 $998244353$ 取模之后的结果。

Solution

考虑设 $f_i$ 表示从 $i$ 到 $n$ 的期望局数。

然后有:

其中

然后有 $f_{i + 1} = p_{i + 1}f_{i + 2} + (1 - p_{i + 1})f_i + 1$。

移项,得:

把那个 $(1 - p_{i + 1})$ 除过去,得到:

然后你不停代换到 $f_0$,最后解一下方程就好了。

啊还有另一种方法:

你设 $f_i$ 表示从关卡 $i$ 到关卡 $(i + 1)$ 所需的期望步数。

那么有:

那个 1 就是你无论赢不赢你都要打一盘,赢了就直接过关了,输了就还要加上后面的 $(1 - p_i)(f_{i - 1} + f_i)$ 的代价。

然后那个 $(1 - p_i)$ 就是输了的概率嘛,你输了就会回到第 $(i - 1)$ 关嘛对不对。

然后你再花 $f_{i - 1}$ 局的期望步数到关卡 $i$,然后再花 $f_i$ 的期望局数过关嘛对吧。

然后化简一下上述式子就可以 $O(n)$ 做啦。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <cstdio>
#define mod 998244353
#define maxN 1000010
long long f[maxN];
long long pow (long long x, long long y)
{
if(!y)
{
return 1;
}
else
{
long long dq = pow(x, y >> 1);
if(!(y & 1))
{
return dq * dq % mod;
}
else
{
return dq * dq % mod * x % mod;
}
}
}
long long inv (long long x)
{
return pow(x, mod - 2);
}
int main ()
{
long long n = 0;
scanf("%lld", &n);
long long A = 0, B = 0;
scanf("%lld %lld", &A, &B);
f[1] = B * inv(A) % mod;
long long Sum = f[1];
for(long long i = 1;i < n; i++)
{
long long x = 0, y = 0;
scanf("%lld %lld", &x, &y);
Sum = (Sum * (y * inv(x) % mod - 1) % mod) + (y * inv(x) % mod);
Sum %= mod;
f[i + 1] = f[i] + Sum;
f[i + 1] %= mod;
}
printf("%lld", f[n]);
return 0;
}