题解:P15970 树上检查

· · 题解

审核题解,管理员辛苦了。

首先 k\le 2 是简单的,k=1 输出 n,k=2 输出 C_n^2。

我们先考虑 k=3,不难发现一个选点方式答案要么是 1,要么是 2,而贡献为 1 的方案就是选的点可以在一条简单路径上。

我们设贡献为 1 的选点方案为 s(显然在一条路径上更好算),那么答案就是 s+2\times (C_n^k-s) 也就是 2\times C_n^k-s。

我们先考虑 k=3 的情况,我们钦定贡献计算在简单路径上的端点,且端点必选(防止算重)。

那么 s=\sum_{u<v} d(u,v)-1 其中 d(u,v) 表示 u 与 v 之间的距离(边数)。

我们现在只要算出 $\sum d$ 即可,这显然是好做的,直接换根即可。 我们考虑 $k=4$,$s=\sum_{u<v} C_{d(u,v)-1}^2$ 直接展开组合数变为只跟 $d^2$,$d$,有关的式子,同理直接换根即可。 换根式子很好推,就不推了(注意算出来的值需要除以 $2$)。 ```cpp #include <bits/stdc++.h> #define int long long using namespace std; const int mod=998244353; int k,ans,dis; int sz[200005],fac[200005],sq[200005],dep[200005],dp[200005],dp2[200005],dep2[200005]; vector <int> mp[200005]; int n; int C(int n,int m) { if(n<m) return 0; return fac[n]*sq[n-m]%mod*sq[m]%mod; } int qpow(int x,int y) { int res=1; while(y) { if(y&1) { res=res*x%mod; } x=x*x%mod; y>>=1; } return res; } void init(int u,int fa) { sz[u]=1; for(int i=0;i<mp[u].size();i++) { int v=mp[u][i]; if(v==fa) continue; init(v,u); sz[u]+=sz[v]; dep[u]+=sz[v]+dep[v]; dep[u]%=mod; dep2[u]+=dep2[v]+2*dep[v]+sz[v]; dep2[u]%=mod; } } void dfs(int u,int fa) { for(int i=0;i<mp[u].size();i++) { int v=mp[u][i]; if(v==fa) continue; dp[v]=dp[u]-sz[v]+n-sz[v]; dp2[v]=dp2[u]+2*dp[u]+n-4*(dep[v]+sz[v]); dp2[v]=(dp2[v]%mod+mod)%mod; dfs(v,u); } } signed main() { fac[0]=sq[0]=1; for(int i=1;i<=200004;i++) fac[i]=fac[i-1]*i%mod,sq[i]=qpow(fac[i],mod-2); int t; cin>>t; while(t--) { cin>>n>>k; for(int i=1;i<n;i++) { int u,v; cin>>u>>v; mp[u].push_back(v); mp[v].push_back(u); } if(k==1) cout<<n<<endl; if(k==2) cout<<n*(n-1)/2%mod<<endl; init(1,0); int sumd=0; dp[1]=dep[1]; dp2[1]=dep2[1]; dfs(1,0); if(k==3) { for(int i=1;i<=n;i++) sumd+=dp[i],sumd%=mod; cout<<(2*C(n,3)-sumd*sq[2]%mod+C(n,2)%mod+mod)%mod<<endl; } if(k==4) { int sumd2=0; for(int i=1;i<=n;i++) sumd+=dp[i],sumd%=mod,sumd2+=dp2[i],sumd2%=mod; cout<<((2*C(n,4)-(sumd2*sq[2]%mod*sq[2]%mod-3*sumd*sq[2]%mod*sq[2]%mod+C(n,2)%mod))%mod+mod)%mod<<endl; } ans=0; for(int i=1;i<=n;i++) mp[i].clear(),sz[i]=dep[i]=dp[i]=dep2[i]=dp2[i]=0; } } ```