HDU4625 JZPTREE 【树形DP】【第二类斯特林数】

时间:2022-11-12 16:17:46

题目大意:

对1到n求题目中描述的那个式子。

题目分析:

幂不好处理,转化为斯特林数。

根据$ n^k= \sum_ { i=0 }^k S(k,i)×i!×C(n,i) $。

我们可以将问题转化为对每个u和$ j=1 \sim k $求$ \sum_ { i=1 }^n \binom{dist(u,i)}{j} $。 通过杨辉三角向子树做一遍树形DP,再向父亲做一遍树形DP即可。

代码:

 #include<bits/stdc++.h>
using namespace std; const int mod = ; int n,k; int S[][];
int f[][];
int fac[];
vector <int> g[]; void init(){
memset(f,,sizeof(f));
} void read(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) g[i].clear();
for(int i=;i<n;i++){
int u,v; scanf("%d%d",&u,&v);
g[u].push_back(v); g[v].push_back(u);
}
} void dfs1(int now,int fa){
for(int i=;i<g[now].size();i++){
if(g[now][i] == fa) continue;
dfs1(g[now][i],now);
f[now][] += f[g[now][i]][];
f[now][] %= mod;
for(int j=;j<=k;j++){
f[now][j] += f[g[now][i]][j] + f[g[now][i]][j-];
f[now][j] %= mod;
}
}
f[now][] ++;
} void dfs2(int now,int fa){
for(int i=;i<g[now].size();i++){
if(g[now][i] == fa) continue;
for(int j=k;j>=;j--){
int p = f[now][j]-f[g[now][i]][j]-f[g[now][i]][j-];
p = ((p%mod)+mod)%mod;
int q=f[now][j-]-f[g[now][i]][j-]-(j->=?f[g[now][i]][j-]:);
q = ((q%mod)+mod)%mod;
f[g[now][i]][j] += p+q;
f[g[now][i]][j] %= mod;
}
f[g[now][i]][] += f[now][] - f[g[now][i]][];
f[g[now][i]][] %= mod;
dfs2(g[now][i],now);
}
} void work(){
dfs1(,);
dfs2(,);
for(int i=;i<=n;i++){
int ans = ;
for(int j=;j<=k;j++){
int nowans = (((fac[j]*f[i][j])%mod)*S[k][j])%mod;
ans += nowans; ans %= mod;
}
printf("%d\n",ans);
}
} int main(){
int t; scanf("%d",&t);
fac[] = ;
for(int i=;i<=;i++) S[i][] = ,fac[i] = (fac[i-]*i)%mod;
for(int i=;i<=;i++){
for(int j=;j<=i;j++) S[i][j] = (S[i-][j-]+j*S[i-][j])%mod;
}
while(t--){
init();
read();
work();
}
return ;
}