Luogu P4827 [国家集训队] Crash 的文明世界
\[\begin{aligned}
S(u)&=\sum\limits_{v=1}^n\operatorname{dis}(u,v)^k\\
&=\sum\limits_{v=1}^n\sum\limits_{i=0}^k\left\{k\atop i\right\}{\operatorname{dis}(u,v)\choose i}i!\\
&=\sum\limits_{i=0}^ki!\left\{k\atop i\right\}\sum\limits_{v=1}^n{\operatorname{dis}(u,v)\choose i}
\end{aligned}
\]
也就是说现在我们要求
\[\sum\limits_{v=1}^n{\operatorname{dis}(u,v)\choose i}
\]
将其拆为子树内的\(f_{u,i}\)和子树外的\(g_{u,i}\)。
根据\({n\choose m}={n-1\choose m-1}+{n-1\choose m}\)可以得到\(f_{u,i}=\sum f_{v,i}+f_{v,i-1}\)。
\(g\)利用换根dp的方法求出即可。
#include<cctype>
#include<cstdio>
#include<vector>
const int N=50007,M=157,P=10007;
int n,k,fac[M],S[M][M],f[N][M],g[N][M],ans[N];std::vector<int>e[N];
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
void dfs(int u,int fa)
{
f[u][0]=1;
for(int v:e[u])
{
if(v==fa) continue;
dfs(v,u),(f[u][0]+=f[v][0])%=P;
for(int j=1;j<=k;++j) (f[u][j]+=f[v][j-1]+f[v][j])%=P;
}
}
void dp(int u,int fa)
{
if(fa)
{
g[u][0]=n-f[u][0];
for(int j=1;j<=k;++j) g[u][j]=(g[fa][j-1]+g[fa][j]+f[fa][j-1]+f[fa][j]-2*f[u][j-1]-f[u][j]-(j>1? f[u][j-2]:0)+4*P)%P;
}
for(int v:e[u]) if(v^fa) dp(v,u);
}
int main()
{
n=read(),k=read();
for(int i=fac[0]=1;i<=k;++i) fac[i]=i*fac[i-1]%P;
for(int i=S[0][0]=1;i<=k;++i) for(int j=S[i][i]=1;j<i;++j) S[i][j]=(S[i-1][j-1]+j*S[i-1][j])%P;
for(int i=1,u,v;i<n;++i) u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
dfs(1,0),dp(1,0);
for(int i=1;i<=n;++i) for(int j=1;j<=k;++j) ans[i]=(ans[i]+1ll*S[k][j]*fac[j]*(g[i][j]+f[i][j]))%P;
for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
}