题意
给一棵树,设 S ( x ) = ∑ i = 1 n d i s t ( x , i ) k S(x)=\sum\limits_{i=1}^n\mathrm{dist}(x,i)^k S(x)=i=1∑ndist(x,i)k,对每个点求出 S ( x ) S(x) S(x)。
n ≤ 5 × 1 0 4 , k ≤ 150 n\leq 5\times10^4,k\leq150 n≤5×104,k≤150。
题解
不会点分树
首先我们知道第二类斯特林数 S i j S_i^j Sij满足这样一个关系
m n = ∑ i = 0 n S n i i ! C m i m^n=\sum\limits_{i=0}^nS_n^ii!C_m^i mn=i=0∑nSnii!Cmi
套进去
S ( x ) = ∑ i = 1 n ∑ j = 0 k S k j j ! C d i s t ( i , x ) j S(x)=\sum\limits_{i=1}^n\sum\limits_{j=0}^kS_k^jj!C_{\mathrm{dist}(i,x)}^j S(x)=i=1∑nj=0∑kSkjj!Cdist(i,x)j
交换求和符号
S
(
x
)
=
∑
j
=
0
k
S
k
j
j
!
∑
i
=
1
n
C
d
i
s
t
(
i
,
x
)
j
S(x)=\sum\limits_{j=0}^kS_k^jj!\sum\limits_{i=1}^nC_{\mathrm{dist}(i,x)}^j
S(x)=j=0∑kSkjj!i=1∑nCdist(i,x)j
于是我们只要求后面那个
∑
i
=
1
n
C
d
i
s
t
(
i
,
x
)
j
\sum\limits_{i=1}^nC_{\mathrm{dist}(i,x)}^j
i=1∑nCdist(i,x)j即可。
树形dp,设
f
(
x
,
j
)
=
∑
u
∈
X
C
d
i
s
t
(
x
,
u
)
j
f(x,j)=\sum\limits_{u\in X}C_{\mathrm{dist}(x,u)}^j
f(x,j)=u∈X∑Cdist(x,u)j,其中
X
X
X表示以
x
x
x为根的子树(包括
x
x
x本身)。
f
(
x
,
j
)
=
∑
u
∈
X
(
C
d
i
s
t
(
x
,
u
)
−
1
j
+
C
d
i
s
t
(
x
,
u
)
−
1
j
−
1
)
f(x,j)=\sum\limits_{u\in X}(C_{\mathrm{dist}(x,u)-1}^j+C_{\mathrm{dist}(x,u)-1}^{j-1})
f(x,j)=u∈X∑(Cdist(x,u)−1j+Cdist(x,u)−1j−1)
u u u到 x x x的距离为 d i s t ( x , u ) \mathrm{dist}(x,u) dist(x,u), u u u又是 X X X中的点,那么与 u u u相距 d i s t ( x , u ) − 1 \mathrm{dist}(x,u)-1 dist(x,u)−1的点也就是 x x x的孩子了。所以我们有转移
f ( x , j ) = ∑ v ∈ s o n ( x ) f ( v , j ) + f ( v , j − 1 ) f(x,j)=\sum\limits_{v\in \mathrm{son}(x)}f(v,j)+f(v,j-1) f(x,j)=v∈son(x)∑f(v,j)+f(v,j−1)
其中 s o n ( x ) \mathrm{son}(x) son(x)是 x x x的孩子集合。
这样还不够,我们还需要求 g ( x , j ) = ∑ u ∉ X C d i s t ( x , u ) j g(x,j)=\sum\limits_{u\notin X}C_{\mathrm{dist}(x,u)}^j g(x,j)=u∈/X∑Cdist(x,u)j。
g ( x , j ) = ∑ u ∉ X ( C d i s t ( x , u ) − 1 j + C d i s t ( x , u ) − 1 j − 1 ) g(x,j)=\sum\limits_{u\notin X}(C_{\mathrm{dist}(x,u)-1}^j+C_{\mathrm{dist}(x,u)-1}^{j-1}) g(x,j)=u∈/X∑(Cdist(x,u)−1j+Cdist(x,u)−1j−1)
=
∑
u
∉
X
(
C
d
i
s
t
(
f
a
(
x
)
,
u
)
j
+
C
d
i
s
t
(
f
a
(
x
)
,
u
)
j
−
1
)
=\sum\limits_{u\notin X}(C_{\mathrm{dist}(\mathrm{fa}(x),u)}^j+C_{\mathrm{dist}(\mathrm{fa}(x),u)}^{j-1})
=u∈/X∑(Cdist(fa(x),u)j+Cdist(fa(x),u)j−1)
其中
∑
u
∉
X
C
d
i
s
t
(
f
a
(
x
)
,
u
)
j
=
f
(
f
a
(
x
)
,
j
)
+
g
(
f
a
(
x
)
,
j
)
−
f
(
x
,
j
)
−
f
(
x
,
j
−
1
)
\sum\limits_{u\notin X}C_{\mathrm{dist}(\mathrm{fa}(x),u)}^j=f(\mathrm{fa}(x),j)+g(\mathrm{fa}(x),j)-f(x,j)-f(x,j-1)
u∈/X∑Cdist(fa(x),u)j=f(fa(x),j)+g(fa(x),j)−f(x,j)−f(x,j−1)
∑
u
∉
X
C
d
i
s
t
(
f
a
(
x
)
,
u
)
j
−
1
=
f
(
f
a
(
x
)
,
j
−
1
)
+
g
(
f
a
(
x
)
,
j
−
1
)
−
f
(
x
,
j
−
1
)
−
f
(
x
,
j
−
2
)
\sum\limits_{u\notin X}C_{\mathrm{dist}(\mathrm{fa}(x),u)}^{j-1}=f(\mathrm{fa}(x),j-1)+g(\mathrm{fa}(x),j-1)-f(x,j-1)-f(x,j-2)
u∈/X∑Cdist(fa(x),u)j−1=f(fa(x),j−1)+g(fa(x),j−1)−f(x,j−1)−f(x,j−2)
做完了。
至于斯特林数怎么求,由于这里只要 k × k k\times k k×k范围内的,所以直接利用递推关系
S i j = S i − 1 j − 1 + j S i − 1 j S_i^j=S_{i-1}^{j-1}+jS_{i-1}^j Sij=Si−1j−1+jSi−1j
就行了,不需要NTT之类的复杂玩意。
#include <cctype>
#include <cstdio>
#include <climits>
#include <algorithm>
#include <vector>
template <typename T> inline void read(T& x) {
int f = 0, c = getchar(); x = 0;
while (!isdigit(c)) f |= c == '-', c = getchar();
while (isdigit(c)) x = x * 10 + c - 48, c = getchar();
if (f) x = -x;
}
template <typename T, typename... Args>
inline void read(T& x, Args&... args) {
read(x); read(args...);
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + 48);
}
template <typename T> inline void writeln(T x) { write(x); puts(""); }
template <typename T> inline bool chkmin(T& x, const T& y) { return y < x ? (x = y, true) : false; }
template <typename T> inline bool chkmax(T& x, const T& y) { return x < y ? (x = y, true) : false; }
const int mod = 10007;
const int maxn = 5e4 + 7, maxk = 157;
int stir[maxk][maxk], f[maxn][maxk], g[maxn][maxk], fac[maxk];
std::vector<int> G[maxn];
int n, K;
void dfs1(int x, int fa) {
f[x][0] = 1;
for (auto v : G[x]) if (v != fa) {
dfs1(v, x);
f[x][0] = (f[x][0] + f[v][0]) % mod;
for (int j = 1; j <= K; ++j)
f[x][j] = (f[x][j] + f[v][j] + f[v][j - 1]) % mod;
}
}
void dfs2(int x, int fa) {
if (x > 1) {
g[x][0] = n - f[x][0];
g[x][1] = ((f[fa][1] + g[fa][1] + f[fa][0] + g[fa][0] - f[x][1] - 2 * f[x][0]) % mod + mod) % mod;
for (int j = 2; j <= K; ++j)
g[x][j] = ((f[fa][j] + g[fa][j] + f[fa][j - 1] + g[fa][j - 1] - f[x][j] - 2 * f[x][j - 1] - f[x][j - 2]) % mod + mod) % mod;
}
for (auto v : G[x]) if (v != fa) dfs2(v, x);
}
int main() {
read(n, K);
for (int i = 1, x, y; i < n; ++i) {
read(x, y);
G[x].push_back(y);
G[y].push_back(x);
}
stir[0][0] = 0; stir[1][1] = 1;
for (int i = 2; i <= K; ++i)
for (int j = 1; j <= i; ++j)
stir[i][j] = (stir[i - 1][j - 1] + j * stir[i - 1][j] % mod) % mod;
fac[0] = 1;
for (int i = 1; i <= K; ++i) fac[i] = fac[i - 1] * i % mod;
dfs1(1, 0);
dfs2(1, 0);
for (int i = 1; i <= n; ++i) {
int si = 0;
for (int j = 0; j <= K; ++j)
si = (si + stir[K][j] * fac[j] % mod * (f[i][j] + g[i][j]) % mod) % mod;
writeln(si);
}
return 0;
}