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;
}

希望能帮助到大家!

posted @ 2023-06-07 18:22  liangbowen  阅读(32)  评论(0编辑  收藏  举报