题目大意:
给定一棵树,求每一个点的 s ( i ) = ∑ j = 1 d i s ( i , j ) k s(i)=\sum_{j=1}dis(i,j)^k s(i)=∑j=1dis(i,j)k。
思路:
题目所求 s ( i ) = ∑ j = 1 d i s ( i , j ) k s(i)=\sum_{j=1}dis(i,j)^k s(i)=∑j=1dis(i,j)k,考虑 k k k次幂的组合意义, x k x^k xk表示 k k k个不同的物品放入 x x x个不同的箱子里面,即 x k = ∑ i = 1 x ( x i ) \{ k i \} × i ! x^k=\sum_{i=1}^{x}{x \choose i}{k\brace i}\times i! xk=∑i=1x(ix){ik}×i!。
对于每一个点
u
u
u,我们所求的就是:
∑
i
∑
j
=
1
k
(
d
i
s
(
u
,
i
)
j
)
\{
k
j
\}
×
j
!
=
∑
j
=
1
k
\{
k
j
\}
×
j
!
∑
i
(
d
i
s
(
u
,
i
)
j
)
\begin{aligned} &\sum_{i}\sum_{j=1}^{k}{dis(u,i)\choose j}{k\brace j}\times j!\\ &=\sum_{j=1}^{k}{k\brace j}\times j!\sum_{i}{dis(u,i)\choose j}\\ \end{aligned}
i∑j=1∑k(jdis(u,i)){jk}×j!=j=1∑k{jk}×j!i∑(jdis(u,i))
设
f
u
,
j
f_{u,j}
fu,j表示点
u
u
u的子树内组合数下标为
j
j
j的
∑
i
(
d
i
s
(
u
,
i
)
j
)
\sum_{i}{dis(u,i)\choose j}
∑i(jdis(u,i)),其中距离转移过来时需要强制+1,这可以利用组合数的简单递推公式来实现,不难得到状态转移方程:
f
u
,
j
=
f
s
o
n
,
j
+
f
s
o
n
,
j
−
1
f_{u,j}=f_{son,j}+f_{son,j-1}
fu,j=fson,j+fson,j−1
设
g
u
,
j
g_{u,j}
gu,j表示整个树上和
u
u
u相关的节点的组合数和,同理可得状态转移方程:
g
u
,
j
=
f
u
,
j
+
g
f
a
,
j
−
(
f
u
,
j
+
f
u
,
j
−
1
)
+
g
f
a
,
j
−
1
−
(
f
u
,
j
−
1
+
f
u
,
j
−
2
)
g_{u,j}=f_{u,j}+g_{fa,j}-(f_{u,j}+f_{u,j-1})+g_{fa,j-1}-(f_{u,j-1}+f_{u,j-2})
gu,j=fu,j+gfa,j−(fu,j+fu,j−1)+gfa,j−1−(fu,j−1+fu,j−2)
然后就愉快的写完了。
/*=======================================
* Author : ylsoi
* Time : 2019.1.28
* Problem : bzoj2159
* E-mail : ylsoi@foxmail.com
* ====================================*/
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<<x<<" "
#define fi first
#define se second
#define mk make_pair
#define pb push_back
typedef long long ll;
using namespace std;
void File(){
freopen("bzoj2159.in","r",stdin);
freopen("bzoj2159.out","w",stdout);
}
template<typename T>void read(T &_){
_=0; T fl=1; char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())_=(_<<1)+(_<<3)+(ch^'0');
_*=fl;
}
const int maxn=5e4+10;
const int maxk=150+10;
const int mod=10007;
int n,k,f[maxn][maxk],g[maxn][maxk],ans[maxn];
int beg[maxn],las[maxn<<1],to[maxn<<1],cnte=1;
int fac[maxk],S[maxk][maxk];
void add(int u,int v){
las[++cnte]=beg[u],beg[u]=cnte,to[cnte]=v;
las[++cnte]=beg[v],beg[v]=cnte,to[cnte]=u;
}
void math_init(){
fac[0]=1;
REP(i,1,k)fac[i]=fac[i-1]*i%mod;
S[0][0]=1;
REP(i,1,k)REP(j,1,i)
S[i][j]=(S[i-1][j-1]+S[i-1][j]*j)%mod;
}
void ad(int &_,int __){
_=(_+__)%mod;
}
void dfs1(int u,int fh){
for(int i=beg[u];i;i=las[i]){
int v=to[i];
if(v==fh)continue;
dfs1(v,u);
REP(j,0,k){
ad(f[u][j],f[v][j]);
if(j)ad(f[u][j],f[v][j-1]);
}
}
ad(f[u][0],1);
}
void dfs2(int u,int fh){
for(int i=beg[u];i;i=las[i]){
int v=to[i];
if(v==fh)continue;
REP(j,0,k){
ad(g[v][j],f[v][j]+g[u][j]-f[v][j]);
if(j>0)ad(g[v][j],-f[v][j-1]+g[u][j-1]-f[v][j-1]);
if(j>1)ad(g[v][j],-f[v][j-2]);
}
dfs2(v,u);
}
}
int main(){
File();
read(n),read(k);
math_init();
int u,v;
REP(i,2,n){
read(u),read(v),add(u,v);
}
dfs1(1,0);
memcpy(g[1],f[1],sizeof(f[1]));
dfs2(1,0);
REP(i,1,n){
REP(j,1,k)
ad(ans[i],g[i][j]*fac[j]%mod*S[k][j]%mod);
ans[i]=(ans[i]+mod)%mod;
}
REP(i,1,n)printf("%d\n",ans[i]);
return 0;
}