Description
传送门
给你一个n个点的树,边权为1. 对于每个点u, 求:(sum_{i = 1}^{n} distance(u, i)^{k})
$ n leq 50000, k leq 150 $
Solution
咱们化一下式子:
(sum_{i = 1}^{n} distance(u,i) ^ {k})
(=sum_{i = 1}^{n} sum_{j = 0}^{k} C(dis(u, i), j)* S2(k, j) * j!)
(=sum_{j = 0}^{k} S2(k,j) * j! * sum_{i = 1}^{n} C(dis(u, i), j))
令(dp[u][j] = sum_{i = 1}^{n} C(dis(u, i), j))
那么设$down[u][j] $ 表示(i in subtree[u])的解, (up[u][j])表示$ i in tree - subtree[u]$的解
那么显然, 根据组合数性质:$${n choose k} = {n - 1 choose k} + {n - 1 choose k - 1}$$
[down[u][j] = down[son][j - 1] + down[son][j]
]
[up[x][k]=up[x][k]+up[fa][k]+up[fa][k-1]
]
[up[x][k]=up[x][k]+down[fa][k]+down[fa][k-1]
]
[up[x][k]=up[x][k]-down[x][k]-down[x][k-1]
]
[up[x][k]=up[x][k]-down[x][k-1]-down[x][k-2]
]
Codes
#include<bits/stdc++.h>
using namespace std;
#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 clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(s) debug("The massage in line %d, Function %s: %s
", __LINE__, __FUNCTION__, s)
typedef long long LL;
typedef long double LD;
const int BUF_SIZE = (int)1e6 + 10;
struct fastIO {
char buf[BUF_SIZE], buf1[BUF_SIZE];
int cur, cur1;
FILE *in, *out;
fastIO() {
cur = BUF_SIZE, in = stdin, out = stdout;
cur1 = 0;
}
inline char getchar() {
if(cur == BUF_SIZE) fread(buf, BUF_SIZE, 1, in), cur = 0;
return *(buf + (cur++));
}
inline void putchar(char ch) {
*(buf1 + (cur1++)) = ch;
if (cur1 == BUF_SIZE) fwrite(buf1, BUF_SIZE, 1, out), cur1 = 0;
}
inline int flush() {
if (cur1 > 0) fwrite(buf1, cur1, 1, out);
return cur1 = 0;
}
}IO;
#define getchar IO.getchar
#define putchar IO.putchar
int read() {
char ch = getchar();
int x = 0, flag = 1;
for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
return x * flag;
}
void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar(x % 10 + 48);
}
void putString(char s[], char EndChar = '
') {
rep(i, 0, strlen(s) - 1) putchar(*(s + i));
if(~EndChar) putchar(EndChar);
}
#define Mod 10007
#define Maxn 50009
#define Maxk 159
struct edge {
int to, nxt;
}g[Maxn << 1];
int n, k, head[Maxn], e, fac[Maxn], up[Maxn][Maxk], down[Maxn][Maxk], s[Maxk][Maxk];
namespace INIT {
void add(int u, int v) {
g[++e] = {v, head[u]}, head[u] = e;
}
void Main() {
clar(head, -1);
n = read(), k = read();
rep(i, 1, n - 1) {
int u = read(), v = read();
add(v, u), add(u, v);
}
s[0][0] = 1;
rep(i, 1, k)
rep(j, 1, i) s[i][j] = (s[i - 1][j - 1] + j * s[i - 1][j]) % Mod;
fac[0] = 1;
rep(i, 1, k) fac[i] = fac[i - 1] * i % Mod;
}
}
namespace SOLVE {
int S[Maxn];
void dfs(int u, int fa) {
down[u][0] = 1;
for(int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if(v != fa) {
dfs(v, u);
(down[u][0] += down[v][0]) %= Mod;
rep(j, 1, k) (down[u][j] += (down[v][j] + down[v][j - 1]) % Mod) %= Mod;
}
}
}
void dfs1(int u, int fa) {
for(int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if(v != fa) {
up[v][0] = (n - down[v][0]) % Mod;
rep(j, 1, k) {
(up[v][j] += up[u][j - 1] + up[u][j]) %= Mod;
(up[v][j] += down[u][j - 1] + down[u][j]) %= Mod;
(up[v][j] -= (down[v][j - 1] + down[v][j - 2]) % Mod - Mod) %= Mod;
(up[v][j] -= (down[v][j - 1] + down[v][j]) % Mod - Mod) %= Mod;
}
dfs1(v, u);
}
}
}
void Main() {
dfs(1, 0), dfs1(1, 0);
rep(i, 1, k) {
int Tmp = fac[i] * s[k][i] % Mod;
rep(j, 1, n) S[j] += (Tmp * (up[j][i] + down[j][i])) % Mod;
}
rep(i, 1, n) printf("%d
", S[i] % Mod);
}
}
int main() {
#ifdef Qrsikno
freopen("BZOJ2159.in", "r", stdin);
freopen("BZOJ2159.out", "w", stdout);
#endif
INIT :: Main();
SOLVE :: Main();
#ifdef Qrsikno
debug("
Running time: %.3lf(s)
", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
return IO.flush();
}