Examples

CF1097G Vladislav and a Great Legend 解题报告

CF1097G Vladislav and a Great Legend解题报告:

更好的阅读体验

题意

给定一个 \(n\) 个节点的树,定义 \(f(S)\)\(S\) 的虚树边数,给定常数 \(k\),求:

\[\sum_{S\in\{1,2,\cdots,n\},S\ne\varnothing}f(S)^k \]

分析

考虑用斯特林数拆开 \(k\) 次幂:

\[\sum_{S\in\{1,2,\cdots,n\},S\ne\varnothing}\sum_{i=0}^n\begin{Bmatrix}k\\i\end{Bmatrix}{f(S)\choose i}i!\\=\sum_{i=0}^n\begin{Bmatrix}k\\i\end{Bmatrix}i!\sum_{S\in\{1,2,\cdots,n\},S\ne\varnothing}{f(S)\choose i} \]

考虑计算后面的贡献,可以考虑用树上背包来计算,这是平凡的。

代码

#include<stdio.h>
#include<vector>
using namespace std;
const int maxn=100005,maxk=205,mod=1000000007;
int n,k,ans;
int S[maxn][maxk],g[maxk],f[maxn][maxk],sz[maxn],fac[maxn],tot[maxn];
vector<int>v[maxn];
void dfs(int x,int last){
	sz[x]=1,f[x][0]=2;
	for(int i=0;i<v[x].size();i++)
		if(v[x][i]!=last){
			int y=v[x][i];
			dfs(y,x);
			for(int u=0;u<=sz[y]&&u<=k;u++)
				tot[u]=(tot[u]-f[y][u]+mod)%mod;
			for(int u=0;u<=sz[x]&&u<=k;u++)
				for(int v=0;v<=sz[y]&&u+v<=k;v++)
					g[u+v]=(g[u+v]+1ll*f[x][u]*f[y][v])%mod;
			sz[x]+=sz[y];
			for(int u=0;u<=k;u++)
				f[x][u]=g[u],g[u]=0;
		}
	for(int i=0;i<=k;i++)
		tot[i]=(tot[i]+f[x][i])%mod;
	for(int i=k;i>=1;i--)
		f[x][i]=(f[x][i]+f[x][i-1])%mod;
	f[x][1]=(f[x][1]-1+mod)%mod;
}
int main(){
	scanf("%d%d",&n,&k);
	fac[0]=fac[1]=S[1][1]=1;
	for(int i=2;i<=k;i++){
		fac[i]=1ll*fac[i-1]*i%mod;
		for(int j=1;j<=k;j++)
			S[i][j]=(S[i-1][j-1]+1ll*j*S[i-1][j])%mod;
	}
	for(int i=1,x,y;i<n;i++)
		scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
	dfs(1,0);
	for(int i=0;i<=k;i++)
		ans=(ans+1ll*S[k][i]*fac[i]%mod*tot[i])%mod;
	printf("%d\n",ans);
	return 0;
}
posted @ 2021-09-13 19:01  xiaoziyao  阅读(44)  评论(0编辑  收藏  举报