[题解][P5206][WC2019] 数树 (op = 1)

简要题意#

给定 n,y

一张图有 |V|=n 个点,现在给出两棵树 T1=G(V,E1)T2=G(V,E2)

定义这两棵树的权值 F(E1,E2)yG=(V,E1E2) 的联通块个数次方。

F(E1,E2)=yn|E1E2|,给定 E1,计算 E2F(E1,E2)

其中 n105。答案对 998244353 取模。

解题思路#

首先我们要找到一个合适的形式来表示我们的答案,部分枚举 S=E1E2,则答案为:

E2S=E1E2yn|S|

其中 S=E1E2 这个恰好的条件限制较强,考虑容斥将限制弱化为 SE1E2.

不妨考虑这样一个容斥原理的式子:

f(S)=TSPT(1)|T||P|f(P)

代入到原来的式子中,得到:

E2S=E1E2yn|S|=E2TE1E2PT(1)|T||P|yn|P|=TE1g(T)PT(1)|T||P|yn|P|=TE1g(T)yn|T|PT(y)|T||P|=TE1g(T)PT(1)|T||P|yn|P|=TE1g(T)yn|T||P|=0|T|(|T||P|)(y)|T||P|=TE1g(T)PT(1)|T||P|yn|P|=TE1g(T)yn|T|(1y)|T|

其中 g(T) 表示包含边集 TE2 的个数。

假设 G=(V,T) 为一个由 k 个大小分别为 ai 的连通块组成的森林,则:

g(T)=nk2i=1kai

继续代入 (注意到 n=|T|+k ),得:

TE1g(T)yn|T|(1y)|T|=TE1nk2i=1kai yk(1y)nk=(1y)nn2TE1i=1kny1y ai

即一个大小为 a 的连通块为答案贡献一个乘积 Ka,其中 K=ny1y

据此可以容易得到一个 O(n2) 的 DP,f(x,i) 表示 x 的子树中,x 所在的连通块大小为 i 的答案。

考虑到这个贡献可以拆分表示为 i=1k(K+K+K+K),故合并两个大小分别为 x,y 的连通块时,新的贡献其实就是 K(x+y)inowKai.

这样状态可以优化为 f(x,0/1) 表示 x 的子树中,当前连通块是否已经做出贡献。

那么转移就是 (前面是选边 (x,y),后面是不选):

f(x,1)=f(x,1)f(y,1) + f(x,1)f(y,0)+f(x,0)f(y,1)f(x,0)=f(x,0)f(y,1) + f(x,0)f(y,0)

代码#

void dfs(int x, int fx){
	siz[x] = 1, f[x] = coef, g[x] = 1;
	for(int i = head[x]; i; i = e[i].nx){
		int y = e[i].to; if(y == fx) continue;
		dfs(y, x);
		int sum = Mod((LL) f[x] * g[y] % mod + (LL) g[x] * f[y] % mod - mod);
		MOD(f[x] = (LL) f[x] * f[y] % mod + sum - mod);
		MOD(g[x] = (LL) g[x] * f[y] % mod + (LL) g[x] * g[y] % mod - mod);
	}
}

void solve(){
    coef = (LL) n * y % mod * qpow(1 - y + mod) % mod;
    dfs(1, 0);
    cout << (LL) f[1] * qpow(1 - y + mod, n) % mod * qpow((LL) n * n % mod) % mod << endl;
}
posted @   IrisT  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩