简要题意#
给定 n,y。
一张图有 |V|=n 个点,现在给出两棵树 T1=G(V,E1) 和 T2=G(V,E2)。
定义这两棵树的权值 F(E1,E2) 为 y 的 G′=(V,E1∩E2) 的联通块个数次方。
即 F(E1,E2)=yn−|E1∩E2|,给定 E1,计算 ∑E2F(E1,E2)。
其中 n≤105。答案对 998244353 取模。
解题思路#
首先我们要找到一个合适的形式来表示我们的答案,部分枚举 S=E1∩E2,则答案为:
∑E2∑S=E1∩E2yn−|S|
其中 S=E1∩E2 这个恰好的条件限制较强,考虑容斥将限制弱化为 S⊆E1∩E2.
不妨考虑这样一个容斥原理的式子:
f(S)=∑T⊆S∑P⊆T(−1)|T|−|P|f(P)
代入到原来的式子中,得到:
∑E2∑S=E1∩E2yn−|S|=∑E2∑T⊆E1∩E2∑P⊆T(−1)|T|−|P|yn−|P|=∑T⊆E1g(T)∑P⊆T(−1)|T|−|P|yn−|P|=∑T⊆E1g(T)yn−|T|∑P⊆T(−y)|T|−|P|=∑T⊆E1g(T)∑P⊆T(−1)|T|−|P|yn−|P|=∑T⊆E1g(T)yn−|T||T|∑|P|=0(|T||P|)(−y)|T|−|P|=∑T⊆E1g(T)∑P⊆T(−1)|T|−|P|yn−|P|=∑T⊆E1g(T)yn−|T|(1−y)|T|
其中 g(T) 表示包含边集 T 的 E2 的个数。
假设 G=(V,T) 为一个由 k 个大小分别为 ai 的连通块组成的森林,则:
g(T)=nk−2k∏i=1ai
继续代入 (注意到 n=|T|+k ),得:
∑T⊆E1g(T)yn−|T|(1−y)|T|=∑T⊆E1nk−2k∏i=1ai yk(1−y)n−k=(1−y)nn2∑T⊆E1k∏i=1ny1−y ai
即一个大小为 a 的连通块为答案贡献一个乘积 Ka,其中 K=ny1−y。
据此可以容易得到一个 O(n2) 的 DP,f(x,i) 表示 x 的子树中,x 所在的连通块大小为 i 的答案。
考虑到这个贡献可以拆分表示为 ∏ki=1(K+K+K+⋯K),故合并两个大小分别为 x,y 的连通块时,新的贡献其实就是 K(x+y)∏i≠nowKai.
这样状态可以优化为 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】