题目链接:https://www.luogu.com.cn/problem/P8208
解题思路:
定义 \(d_u\) 表示节点 \(u\) 的出度,定义 \(V_u\) 表示节点 \(u\) 一步能够走到的节点的集合。
定义状态 \(p_{u, c, v}\) 表示从节点 \(u\) 出发走恰好 \(c\) 步的情况下,至少经过一次节点 \(v\) 的概率。
则:
- 若 \(v = u\),则 \(p_{u, c, v} = 1\);
- 否则,若 \(c = 0\),则 \(p_{u, c, v} = 0\);
- 否则,\(p_{u, c, v} = \frac{1}{d_u} \sum\limits_{x \in V_u} p(x, c-1, v)\)
定义 \(f_{u, c}\) 表示从节点 \(u\) 开始走恰好 \(c\) 步,废话指数的期望值,则:
- 若 \(c = 0\),则 \(f_{u, 0} = 0\);
- 否则,\(f(u, c) = \frac{1}{d_u} \sum\limits_{v \in V_u} f(v, c-1) + v \times p(v, c-1, u)\)
注:这道题目的意思有点绕 如果是从 \(u\) 先走到 \(v\),然后再绕回 \(u\),则额外增加的代价是 \(v\),而不是 \(u\)。所以会看见,上式中额外增加的代价是 \(v\) 而不是 \(u\)。即标下划线的部分:
\[f(u, c) = \frac{1}{d_u} \sum\limits_{v \in V_u} f(v, c-1) + \underline{v} \times p(v, c-1, u)
\]
这里是 \(v\) 不是 \(u\)。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
typedef long long ll;
void gcd(ll a , ll b , ll &d , ll &x , ll &y) {if(!b) {d = a; x = 1; y = 0;}else { gcd(b , a%b,d,y , x); y -= x * (a/b); }
}
ll inv(ll a , ll n = mod) {ll d , x , y;gcd(a , n , d, x , y);return d == 1 ? (x+n)%n : -1;
}ll p[105][105][105], f[105][105], d[105];
bool visp[105][105][105], visf[105][105];
vector<int> g[105];
int n, s, T;ll dfsp(int u, int c, int v) {if (v == u) return 1;if (c == 0) return 0;if (visp[u][c][v])return p[u][c][v];visp[u][c][v] = true;ll res = 0;for (auto x : g[u])res += dfsp(x, c-1, v),res %= mod;res = res * inv(d[u]) % mod;return p[u][c][v] = res;
}ll dfsf(int u, int c) {if (c == 0) return 0;if (visf[u][c])return f[u][c];visf[u][c] = true;ll res = 0;for (auto v : g[u])res += dfsf(v, c-1) + v * dfsp(v, c-1, u) % mod,res %= mod;res = res * inv(d[u]) % mod;return f[u][c] = res;
}int main() {cin >> n >> s >> T;for (int u = 1; u <= n; u++) {cin >> d[u];for (int j = 0; j < d[u]; j++) {int v;cin >> v;g[u].push_back(v);}}cout << dfsf(s, T) << endl;return 0;
}