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=1ndist(i,n)k=i=1nj=0nS(k,j)Cdist(i,n)jj!=j=0nS(k,j)j!i=1nCdist(i,n)j=j=0nS(k,j)j!i=1n(Cdist(i,n)1j+Cdist(i,n)1j1)
然后后面那个是可以直接树形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;
}
posted @ 2021-07-23 12:20  lahlah  阅读(44)  评论(0编辑  收藏  举报