[luogu P4827] [国家集训队] Crash 的文明世界

\(\text{Problem}:\)[国家集训队] Crash 的文明世界

\(\text{Solution}:\)

先将 \(x^{k}\) 用第二类斯特林数的形式展开,得到:

\[\begin{aligned} \sum\limits_{j=1}^{n}dist(i,j)^{k}&=\sum\limits_{j=1}^{n}\sum\limits_{x=0}^{k}\binom{dist(i,j)}{x}{k\brace x}x!\\ &=\sum\limits_{x=0}^{k}{k\brace x}x!\sum\limits_{j=1}^{n}\binom{dist(i,j)}{x}\\ &=\sum\limits_{x=0}^{k}{k\brace x}x!\sum\limits_{j=1}^{n}\binom{dist(i,j)-1}{x}+\binom{dist(i,j)-1}{x-1}\\ &=\sum\limits_{x=0}^{k}{k\brace x}x!\cdot F_{i,x} \end{aligned} \]

考虑 \(F_{i,x}\) 的转移式(只计算子树内答案):

\[F_{i,x}=\sum\limits_{v\in son_{i}}F_{son,x}+F_{son,x-1} \]

现在可以在 \(O(nk)\) 的时间复杂度内对每个 \(i\) 求出答案(但还没暴力快)。考虑已知 \(i\),如何利用 \(dp\) 数组 \(F\) 快速求出 \(son_{i}\)。由组合数的性质,有:

\[\binom{dist(i,j)+1}{x}\rightarrow \binom{dist(i,j)}{x}+\binom{dist(i,j)}{x-1} \]

故考虑 \(i\rightarrow v\in son_{i}\) 时,把 \(i\) 其他儿子的贡献相加转移给 \(v\) 即可。总时间复杂度 \(O(nk)\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=50010, M=155, Mod=1e4+7;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,K,S[M][M],F[N][M],fac[M],sum[N];
int head[N],maxE; struct Edge { int nxt,to; }e[N<<1];
inline void Add(int u,int v) { e[++maxE].nxt=head[u]; head[u]=maxE; e[maxE].to=v; }
void DFS1(int x,int fa)
{
	F[x][0]=1;
	for(ri int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		DFS1(v,x);
		for(ri int j=1;j<=K;j++) F[x][j]=(F[x][j]+F[v][j]+F[v][j-1])%Mod;
		F[x][0]=(F[x][0]+F[v][0])%Mod;
	}
}
void DFS2(int x,int fa)
{
	for(ri int i=head[x];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		sum[0]=(F[x][0]-F[v][0]+Mod)%Mod;
		for(ri int j=1;j<=K;j++) sum[j]=(F[x][j]-F[v][j]-F[v][j-1])%Mod, sum[j]=(sum[j]+Mod)%Mod;
		F[v][0]=(F[v][0]+sum[0])%Mod;
		for(ri int j=1;j<=K;j++) F[v][j]=(F[v][j]+sum[j]+sum[j-1])%Mod;
		DFS2(v,x);
	}
}
signed main()
{
	fac[0]=1;
	for(ri int i=1;i<M;i++) fac[i]=fac[i-1]*i%Mod;
	S[0][0]=1;
	for(ri int i=1;i<M;i++)
	{
		for(ri int j=0;j<=i;j++) S[i][j]=(j*S[i-1][j]+S[i-1][j-1])%Mod;
	}
	n=read(), K=read();
	for(ri int i=1;i<n;i++)
	{
		int u,v;
		u=read(), v=read();
		Add(u,v), Add(v,u);
	}
	DFS1(1,0), DFS2(1,0);
	for(ri int i=1;i<=n;i++)
	{
		int ans=0;
		for(ri int j=0;j<=K;j++)
		{
			ans=(ans+fac[j]*S[K][j]%Mod*F[i][j]%Mod)%Mod;
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2021-04-22 08:26  zkdxl  阅读(37)  评论(0编辑  收藏  举报