思路
先令 f(\varnothing)=0,那么原式转为 \sum_{X \sube U} (f(X))^k,容易发现这对答案不会造成影响。
由普通幂转下降幂:
x^k=\sum_{i=0} \begin{Bmatrix} k\\i \end{Bmatrix} \dbinom{x}{i} i!
其中 \begin{Bmatrix} k\\i \end{Bmatrix} 是第二类斯特林数。
带入到原式:
\begin{aligned}
\sum_{X \sube U} (f(X))^k &= \sum_{X \sube U}\sum_{i=0} \begin{Bmatrix} k\\i \end{Bmatrix} \dbinom{f(X)}{i} i!\\
&=\sum_{i=0}\begin{Bmatrix} k\\i \end{Bmatrix}i!\sum_{X \sube U} \dbinom{f(X)}{i}
\end{aligned}
注意到 \begin{Bmatrix} k\\i \end{Bmatrix}i! 可以预处理,于是我们只用尝试求解 \sum_{X \sube U} \dbinom{f(X)}{i}。
考虑组合意义,容易发现 \dbinom{f(X)}{i} 的一个意义是从虚树中选 i 条边出来染色的方案数,我们由此入手。
考虑 dp,容易设计出状态 f_{x,i} 表示以 x 为根的子树中的虚树的染色方案数(x 这个点可以不选,但虚树必须经过 x)。
但是这样难以转移,于是再设计辅助状态 g_{x,i} 表示以 x 为根的子树及 father(x)-x 这条边(后称作父边)必须作为虚树边的染色方案数(x 这个点同样可以不选,父边必须当作虚树边但可以不染色)。
(你会发现 g_{x,i} 在根结点处的定义不清楚,但是根结点处的 g_{x,i} 作为辅助状态不会再往上转移了,所以我们不妨忽略这个问题,或者你也可以认为根结点有一根虚拟父边。)
考虑转移,容易发现:
f_{x,i+j}=f_{x,i} \times g_{y,j},y \in son(x)
$$
g_{x,0}=f_{x,0}\\
g_{x,i}=f_{x,i}+f_{x,i-1}
$$
另外此时 $g_{x,1}$ 会计入一颗空树(仅有父边且染色),需要减一。
注意到此时的 $f_{x,i}$ 还有不合法的情况未剔除,具体来说是所有虚树点都在一颗子树中且 $x$ 本身不选的情况,于是有:
$$
f_{x,i}=f_{x,i}-\sum_{y \in son(x)} g_{y,i}
$$
注意上面这一步要在求完 $g_{x,i}$ 后再进行(因为对于 $g_{x,i}$ 而言,上面那种情况是合法的)。
最后是统计答案,显然直接把每个点的 $f_{x,i}$ 计入 $\sum_{X \sube U} \dbinom{f(X)}{i}$ 即可。
时间复杂度 $O(nk)$。
## code:
```cpp
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,M=210,mod=1e9+7;
int n,K,sum;
int S[M][M],f[N][M],g[N][M],tmp[M],siz[N],fac[N],ans[N];
vector<int> tr[N];
void add(int x,int y){
tr[x].push_back(y);
return;
}
void init(){
S[1][1]=1,fac[0]=1;
for(int i=2;i<=200;i++) for(int j=1;j<=i;j++) S[i][j]=(S[i-1][j-1]+S[i-1][j]*j%mod)%mod;
for(int i=1;i<=200;i++) fac[i]=fac[i-1]*i%mod;
return;
}
void dfs(int x,int fa){
siz[x]=1,f[x][0]=2;
for(int y : tr[x]){
if(y==fa) continue;
dfs(y,x);
for(int i=0;i<=K;i++) tmp[i]=0;
for(int i=0;i<=min(siz[x],K);i++){
for(int j=0;j<=min(siz[y],K-i);j++){
tmp[i+j]=(tmp[i+j]+f[x][i]*g[y][j]%mod)%mod;
}
}
siz[x]+=siz[y];
for(int i=0;i<=K;i++) f[x][i]=tmp[i];
}
g[x][0]=f[x][0];
for(int i=1;i<=K;i++) g[x][i]=(f[x][i]+f[x][i-1])%mod;
g[x][1]=(g[x][1]-1+mod)%mod;
for(int y : tr[x]) if(y!=fa) for(int i=0;i<=K;i++) f[x][i]=(f[x][i]-g[y][i]+mod)%mod;
for(int i=0;i<=K;i++) ans[i]=(ans[i]+f[x][i])%mod;
return;
}
signed main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
init();
cin>>n>>K;
for(int i=1,x,y;i<n;i++){
cin>>x>>y;
add(x,y),add(y,x);
}
dfs(1,0);
for(int i=0;i<=K;i++){
sum=(sum+fac[i]*S[K][i]%mod*ans[i]%mod)%mod;
}
cout<<sum;
return 0;
}
```