luogu P4827 [国家集训队] Crash 的文明世界
https://www.luogu.com.cn/problem/P4827
先推式子
∑
i
=
1
n
d
i
s
t
(
i
,
n
)
k
=
∑
i
=
1
n
∑
j
=
0
n
S
(
k
,
j
)
C
d
i
s
t
(
i
,
n
)
j
j
!
=
∑
j
=
0
n
S
(
k
,
j
)
j
!
∑
i
=
1
n
C
d
i
s
t
(
i
,
n
)
j
=
∑
j
=
0
n
S
(
k
,
j
)
j
!
∑
i
=
1
n
(
C
d
i
s
t
(
i
,
n
)
−
1
j
+
C
d
i
s
t
(
i
,
n
)
−
1
j
−
1
)
\large \sum\limits_{i=1}^n dist(i,n)^k \\ = \sum\limits_{i=1}^n \sum\limits_{j=0}^nS(k, j)C_{dist(i,n)}^j j! \\ = \sum\limits_{j=0}^nS(k,j)j!\sum\limits_{i=1}^nC_{dist(i,n)}^j \\ = \sum\limits_{j=0}^nS(k,j)j!\sum\limits_{i=1}^n(C_{dist(i,n) - 1}^j + C_{dist(i,n) - 1}^{j-1})
i=1∑ndist(i,n)k=i=1∑nj=0∑nS(k,j)Cdist(i,n)jj!=j=0∑nS(k,j)j!i=1∑nCdist(i,n)j=j=0∑nS(k,j)j!i=1∑n(Cdist(i,n)−1j+Cdist(i,n)−1j−1)
然后后面那个是可以直接树形DP出来的,然后再跑一遍换根DP即可
code:
#include<bits/stdc++.h>
#define mod 10007
#define N 50050
#define M 155
using namespace std;
struct edge {
int v, nxt;
} e[N << 1];
int p[N], eid;
void init() {
memset(p, -1, sizeof p);
eid = 0;
}
void insert(int u, int v) {
e[eid].v = v;
e[eid].nxt = p[u];
p[u] = eid ++;
}
int dp[N][M], f[N][M], ls[M], n, k, S[M][M], fac[M];
void dfs(int u, int fa) {
dp[u][0] = 1;
for(int i = p[u]; i + 1; i = e[i].nxt) {
int v = e[i].v;
if(v == fa) continue;
dfs(v, u);
for(int j = 1; j <= k; j ++) dp[u][j] = (dp[u][j] + dp[v][j] + dp[v][j - 1]) % mod;
dp[u][0] = (dp[u][0] + dp[v][0]) % mod;
}
}
void dfss(int u, int fa) {
for(int i = 0; i <= k; i ++) f[u][i] = dp[u][i];
if(fa) {
for(int i = 1; i <= k; i ++) ls[i] = (f[fa][i] - f[u][i] - f[u][i - 1] + 2 * mod) % mod;
ls[0] = (f[fa][0] - f[u][0]);
for(int i = 1; i <= k; i ++) f[u][i] = (f[u][i] + ls[i] + ls[i - 1]) % mod;
f[u][0] = (f[u][0] + ls[0]) % mod;
}
for(int i = p[u]; i + 1; i = e[i].nxt) {
int v = e[i].v;
if(v == fa) continue;
dfss(v, u);
}
}
int main() { init();
scanf("%d%d", &n, &k);
S[0][0] = 1;
for(int i = 1; i <= k; i ++)
for(int j = 1; j <= i; j ++)
S[i][j] = (S[i - 1][j - 1] + j * S[i - 1][j]) % mod;
fac[0] = 1;
for(int i = 1; i <= k; i ++) fac[i] = fac[i - 1] * i % mod;
for(int i = 1; i < n; i ++) {
int u, v;
scanf("%d%d", &u, &v);
insert(u, v), insert(v, u);
}
dfs(1, 0), dfss(1, 0);
for(int i = 1; i <= n; i ++) {
int ans = 0;
for(int j = 0; j <= k; j ++) ans = (ans + S[k][j] * fac[j] % mod * f[i][j] % mod) % mod;
printf("%d\n", ans);
}
return 0;
}