ABC277G 题解
前言
好题,记录一手拆贡献的 trick。
思路
我们需要维护一个 \(x^2\) 的期望 \(f(x^2)\),支持 \(f(x^2) \to f\Big((x+1)^2\Big)\)。
想到 P1654 的 trick,\((x+1)^2 = x^2 + 2x + 1\),只需维护 \(x^2\)、\(x^1\)、\(x^0\) 的转移即可。
大力 DP 即可。设 \(p0_{i,u}\),\(p1_{i,u}\),\(p2_{i,u}\) 分别是 \(x^0\),\(x^1\),\(x^2\),走了 \(i\) 步,现在在 \(u\) 的期望值。
转移方程:\(p_{i,u} = \sum\limits_{u\to v} \frac1{\text{degree}_v} \cdot p_{i-1,v}\)(三个数组都是这样子)。
- 当 \(a_u = 0\) 时,\(p2_{i,u} \gets 2 \cdot p1_{i,u} + p0_{i,u}\),\(p1_{i,u} \gets p0_{i,u}\)。
- 当 \(a_u = 1\) 时,答案即 \(p2_{i,u}\)。
统计所有 \(a_u=1\) 时的答案即可。
代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 3005, mod = 998244353;
struct Edge {int now, nxt;} e[N << 1];
int in[N], inv[N], head[N], cur;
void add(int u, int v)
{
in[u]++;
e[++cur].now = v, e[cur].nxt = head[u];
head[u] = cur;
}
int a[N]; long long p0[N][N], p1[N][N], p2[N][N];
int qpow(int x, int y = mod - 2)
{
int ans = 1;
while (y)
{
if (y & 1) ans = 1ll * ans * x % mod;
x = 1ll * x * x % mod;
y >>= 1;
}
return ans;
}
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
while (m--)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), inv[i] = qpow(in[i]);
int ans = 0;
p0[0][1] = 1;
for (int i = 1; i <= k; i++)
for (int u = 1; u <= n; u++)
{
for (int _ = head[u]; _; _ = e[_].nxt)
{
int v = e[_].now;
(p0[i][u] += p0[i - 1][v] * inv[v]) %= mod;
(p1[i][u] += p1[i - 1][v] * inv[v]) %= mod;
(p2[i][u] += p2[i - 1][v] * inv[v]) %= mod;
}
if (a[u]) ans = (ans + p2[i][u]) % mod;
else
(p2[i][u] += 2 * p1[i][u] + p0[i][u]) %= mod,
(p1[i][u] += p0[i][u]) %= mod;
}
cout << ans;
return 0;
}
希望能帮助到大家!