省选联测 31
worldvanquisher · · 个人记录
啊啊啊今天又保龄了。
今天的题确实很适合倒序开题。然后我正序开的导致半个小时没时间写 T3。
T3 的一些实现比较震撼,所以写点题解。(老是过来人问我 T3 是什么东西所以先写了)
shik 吞进去又吐出来。抵德和 ber ♂ 宇纠缠个不清。天空中的素数还没有降下。
你站在椭圆的一 ♂ 焦,伟大尼特向你发问。
苯为
一看这题求图的点染色方案数然后一脸不可做的样子那就套色多项式吧。
色多项式是什么东西?
以下定义抄自 EI 论文。
对于无向图
那么答案就是
其中 Tutte 多项式为
其中
那么代个数进去。以下
然后我们发现原图是个基环树。那么可以枚举选了几条边,设选了
- 选环:方案数
\dbinom{n-k}{i-k} ,连通块数量n-i+1 。 - 不选环:方案数
\dbinom ni-\dbinom{n-k}{i-k} ,连通块数量n-i 。 那么通通加起来,对于一种环长k 的答案就是:\begin{aligned} &\sum_{i=0}^n(-1)^i\left(\binom nic^{n-i}+\binom{n-k}{i-k}c^{n-i+1}-\binom{n-k}{i-k}c^{n-i}\right)\\ =&(c-1)^n+\sum_{i=0}^n\binom{n-k}{i-k}(-1)^i(c^{n-i+1}-c^{n-i})\\ =&(c-1)^n+(-1)^k(c-1)\sum_{i=0}^{n-k}\binom{n-k}i(-1)^ic^{n-k-i}\\ =&(c-1)^n+(-1)^k(c-1)^{n-k+1} \end{aligned} 那累计所有环长的贡献就能找到答案。然后关于怎么一遍 dfs 就找到所有贡献的问题,我们分离一下无关变量。首先前边的
(c-1)^n 和k 无关,累加n^2 次直接记录进答案。然后看后边的其实就是\frac{(c-1)^{n+1}}{(1-c)^k} 上边系数和
k 没关系提出来,那么设pw_k=\dfrac 1{(1-c)^k} ,只要计算\sum pw_k 。
考虑统计所有路径的贡献。发现我们可以把子树内的路径分为两类:从根节点到子树内部的和跨越根节点的。那么我们统计一下子树答案的前缀和
#include <iostream>
#include <algorithm>
#include <cstdio>
#define int long long
using namespace std;
const int mod=421969921;
int n,A,k,ans,pw[1000010];
struct node{
int v,next;
}edge[2000010];
int t,head[1000010];
void add(int u,int v){
edge[++t].v=v;edge[t].next=head[u];head[u]=t;
}
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return ans;
}
int dfs(int x,int f){
ans=(ans+pw[1])%mod;int sum=pw[1];
for(int i=head[x];i;i=edge[i].next){
if(edge[i].v!=f){
int ret=dfs(edge[i].v,x);
ans=(ans+2ll*sum%mod*ret)%mod;
sum=(sum+1ll*ret*pw[1])%mod;
}
}
return sum;
}
signed main(){
freopen("ber.in","r",stdin);
freopen("ber.out","w",stdout);
scanf("%lld%lld%lld",&n,&A,&k);A++;k%=mod;A%=mod-1;
for(int i=1;i<n;i++){
int u,v;scanf("%lld%lld",&u,&v);
add(u,v);add(v,u);
}
pw[0]=1;pw[1]=qpow(qpow(1-k+mod,mod-2),A);
for(int i=2;i<=n;i++)pw[i]=1ll*pw[i-1]*pw[1]%mod;
dfs(1,0);
ans=1ll*ans*qpow(k-1,(1ll*A*n+1)%(mod-1));
ans=(ans+1ll*qpow(k-1,1ll*A*n%(mod-1))*n%mod*n)%mod;
printf("%lld\n",ans);
return 0;
}