P8774 [蓝桥杯 2022 省 A] 爬树的甲壳虫(概率DP)
[蓝桥杯 2022 省 A] 爬树的甲壳虫
题目描述
有一只甲壳虫想要爬上一颗高度为 \(n\) 的树,它一开始位于树根, 高度为 \(0\),当它尝试从高度 \(i-1\) 爬到高度为 \(i\) 的位置时有 \(P_{i}\) 的概率会掉回树根, 求它从树根爬到树顶时, 经过的时间的期望值是多少。
输入格式
输入第一行包含一个整数 \(n\) 表示树的高度。
接下来 \(n\) 行每行包含两个整数 \(x_{i}, y_{i}\), 用一个空格分隔,表示 \(P_{i}=\frac{x_{i}}{y_{i}}\) 。
输出格式
输出一行包含一个整数表示答案,答案是一个有理数,请输出答案对质数 \(998244353\) 取模的结果。其中有理数 \(\frac{a}{b}\) 对质数 \(P\) 取模的结果是整数 \(c\) 满足 \(0 \leq c<P\) 且 \(c \cdot b \equiv a(\bmod P)\) 。
样例 #1
样例输入 #1
1
1 2
样例输出 #1
2
样例 #2
样例输入 #2
3
1 2
3 5
7 11
样例输出 #2
623902744
提示
对于 \(20 \%\) 的评测用例, \(n \leq 2,1 \leq x_{i}<y_{i} \leq 20\);
对于 \(50 \%\) 的评测用例, \(n \leq 500,1 \leq x_{i}<y_{i} \leq 200\);
对于所有评测用例, \(1 \leq n \leq 10^5,1 \leq x_{i}<y_{i} \leq 10^{9}\) 。
蓝桥杯 2022 省赛 A 组 E 题。
解题思路
令\(f_i\)表示从第\(i\)层爬到第\(n\)层的时间期望。
容易得到:
上面两个式子可以改写成:
由于\(f_n=0\),可以得到\(a_{n-1}=p_n\),\(b_{n-1}=1\)
下面来看下如何由\(a_{n-1},b_{n-1}\)推出\(a_{n-2},b_{n-2}\)
即:
最终有:
只需求得\(a_1\),\(b_1\)即可。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
#define ll long long
const int N = 1e5 + 10;
ll x[N], y[N], p[N];
ll ksm(ll a, ll b)
{
ll ans = 1;
ll base = a;
while (b)
{
if (b & 1)
{
ans *= base;
ans %= mod;
}
base *= base;
base %= mod;
b >>= 1;
}
return ans;
}
int main()
{
int n;
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> x[i] >> y[i];
p[i] = x[i] * ksm(y[i], mod - 2) % mod;
}
ll a = 0, b = 0;
for (int i = n; i >= 1; --i)
{
a = ((a * (1 - p[i]) + p[i]) % mod + mod) % mod;
b = (((1 - p[i] )* b + 1) % mod + mod) % mod;
}
cout << b * ksm(1 - a + mod, mod - 2) % mod;
return 0;
}