Luogu4827 Crash的文明世界 组合、树形DP

传送门



又是喜闻乐见的\(k\)次幂求和题目

那么\(S(x) = \sum\limits_{i=1}^n dist(i,x)^k = \sum\limits_{i=1}^n \sum\limits_{j=1}^k \binom{dist(i,x)}{j} \left\{ \begin{array}{cccc} k \\ j \end{array}\right\} j! = \sum\limits_{j=1}^k \left\{ \begin{array}{cccc} k \\ j \end{array}\right\} j! \sum\limits_{i=1}^n \binom{dist(i,x)}{j}\)。

因为组合数有优秀的性质:\(\binom{i+1}{j}=\binom{i}{j} + \binom{i}{j - 1}\),可以用这一个式子做一个DP。

设\(x\)和\(x\)的子树集合为\(S_x\),\(dp_{i,j}=\sum\limits_{x \in S_i}\binom{dist(i,x)}{j}\),转移的时候考虑\(i\)的孩子\(x\),\(dp_x\)中的所有\(dist\)都会加上\(1\),也就是说\(dp_{i,j} += \sum\limits_{y \in S_x} \binom{dist(x,y)+1}{j} = \sum\limits_{y \in S_x} (\binom{dist(x,y)}{j}+\binom{dist(x,y)}{j-1}) = dp_{x,j}+dp_{x,j-1}\),初始每一个节点\(i\)的\(dp_{i,0}=1\),其余为\(0\)。

接下来设\(up_{i,j} = \sum\limits_{x \not\in S_i}\binom{dist(i,x)}{j}\),转移从一个点\(i\)转移到它的孩子\(x\),将\(dp_x\)对\(dp_i\)的贡献消除之后得到\(dp'_i\),那么不难得到\(up_{x,j} = up_{i,j}+up_{i,j-1}+dp'_{i,j}+dp'_{i,j-1}\)。

最后\(\sum\limits_{i=1}^n \binom{dist(i,x)}{j} = dp_{x,j} + up_{x,j}\)。

#include<bits/stdc++.h>
//this code is written by Itst
using namespace std;

int read(){
    int a = 0; char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return a;
}

const int _ = 50003 , MOD = 10007;
struct Edge{
    int end , upEd;
}Ed[_ << 1];
int dp[_][157] , up[_][157] , tmp[157] , S[157][157] , ans[_];
int N , K , head[_] , cntEd;

void addEd(int a , int b){
    Ed[++cntEd] = (Edge){b , head[a]};
    head[a] = cntEd;
}

void dfs1(int x , int p){//dp
    dp[x][0] = 1;
    for(int i = head[x] ; i ; i = Ed[i].upEd)
        if(Ed[i].end != p){
            dfs1(Ed[i].end , x);
            for(int j = K ; j ; --j)
                dp[x][j] = (dp[x][j] + dp[Ed[i].end][j] + dp[Ed[i].end][j - 1]) % MOD;
            dp[x][0] = (dp[x][0] + dp[Ed[i].end][0]) % MOD;
        }
}

void dfs2(int x , int p){//up
    for(int i = 0 ; i <= K ; ++i)
        tmp[i] = (up[x][i] + dp[x][i]) % MOD;
    for(int i = head[x] ; i ; i = Ed[i].upEd)
        if(Ed[i].end != p){
            up[Ed[i].end][0] = (tmp[0] + MOD - dp[Ed[i].end][0]) % MOD;
            for(int j = 1 ; j <= K ; ++j)
                up[Ed[i].end][j] = (tmp[j] + 2 * MOD - (dp[Ed[i].end][j] + dp[Ed[i].end][j - 1])) % MOD;
            for(int j = K ; j ; --j)
                up[Ed[i].end][j] = (up[Ed[i].end][j] + up[Ed[i].end][j - 1]) % MOD;
        }
    for(int i = head[x] ; i ; i = Ed[i].upEd)
        if(Ed[i].end != p)
            dfs2(Ed[i].end , x);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    //freopen("out","w",stdout);
#endif
    N = read(); K = read();
    for(int i = 1 ; i < N ; ++i){
        int a = read() , b = read();
        addEd(a , b); addEd(b , a);
    }
    S[1][1] = 1;
    for(int i = 2 ; i <= K ; ++i)
        for(int j = 1 ; j <= i ; ++j)
            S[i][j] = (S[i - 1][j - 1] + S[i - 1][j] * j) % MOD;
    dfs1(1 , 0); dfs2(1 , 0);
    int fac = 1;
    for(int j = 1 ; j <= K ; ++j){
        fac = 1ll * fac * j % MOD;
        for(int i = 1 ; i <= N ; ++i)
            ans[i] = (ans[i] + 1ll * (dp[i][j] + up[i][j]) * fac * S[K][j]) % MOD;
    }
    for(int i = 1 ; i <= N ; ++i)
        printf("%d\n" , ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/Itst/p/10843602.html

时间: 2024-08-05 10:33:26

Luogu4827 Crash的文明世界 组合、树形DP的相关文章

BZOJ 2159: Crash 的文明世界(树形dp+第二类斯特林数+组合数)

题意: 给定一棵 \(n\) 个点的树和一个常数 \(k\) , 对于每个 \(i\) , 求 \[\displaystyle S(i) = \sum _{j=1} ^ {n} \mathrm{dist}(i, j)^k\] \(n ≤ 50000, k ≤ 150\) 题解 : 先划划那个 \(S(i)\) 的式子 我们需要知道一个化 \(x^n(n \ge 0)\) 的东西qwq \[\displaystyle x^n=\sum_{k=0}^{n}\begin{Bmatrix} n \\ k

bzoj 2159: Crash 的文明世界

2159: Crash 的文明世界 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 478  Solved: 233[Submit][Status][Discuss] Description Crash 小朋友最近迷上了一款游戏——文明5(Civilization V).在这个游戏中,玩家可以建立和发展自己的国家,通过外交和别的国家交流,或是通过战争征服别的国家.现在Crash 已经拥有了一个N 个城市的国家,这些城市之间通过道路相连.由于建设道路

bzoj 2159 Crash 的文明世界 —— 第二类斯特林数+树形DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159 使用公式:\( n^{k} = \sum\limits_{i=0}^{k} S(k,i) * i! * C_{n}^{i} \) 所以维护 \( f[x][i] = \sum\limits_{u\in subtree[x],d=dist(x,u)}^{n} C_{d}^{i} \) 然后利用 \( C_{n}^{m} = C_{n-1}^{m} + C_{n-1}^{m-1} \),

P4827 [国家集训队] Crash 的文明世界(第二类斯特林数+树形dp)

传送门 对于点\(u\),所求为\[\sum_{i=1}^ndis(i,u)^k\] 把后面那堆东西化成第二类斯特林数,有\[\sum_{i=1}^n\sum_{j=0}^kS(k,j)\times j!\times{dis(i,u)\choose j}\] \[\sum_{j=1}^nS(k,j)\times j!\sum_{i=0}^k{dis(i,u)\choose j}\] 于是对于每个点只要维护好\(\sum_{i=0}^k{dis(i,u)\choose j}\)就好了 因为\({n

【bzoj 2159】Crash 的文明世界

Description Crash小朋友最近迷上了一款游戏——文明5(Civilization V).在这个游戏中,玩家可以建立和发展自己的国家,通过外交和别的国家交流,或是通过战争征服别的国家.现在Crash已经拥有了一个N个城市的国家,这些城市之间通过道路相连.由于建设道路是有花费的,因此Crash只修建了N-1条道路连接这些城市,不过可以保证任意两个城市都有路径相通.在游戏中,Crash需要选择一个城市作为他的国家的首都,选择首都需要考虑很多指标,有一个指标是这样的:$S(i)=\sum

【[国家集训队] Crash 的文明世界】

先写一个五十分的思路吧 首先这道题有一个弱化版 [POI2008]STA-Station 相当于\(k=1\),于是就是一个非常简单的树形\(dp\)的\(up\ \ and\ \ down\)思想 但是我们现在要求的是这个柿子了 \[\sum_{j=1}^ndis(i,j)^k\] 感觉这个东西很组合数学啊,感觉这个柿子像是天生为二项式定理准备的 我们还是考虑树形\(dp\) 在第一遍\(up\)的时候,我们设\(dp[i][k]\)表示 \[\sum_{j\in{i}}dis(i,j)^k\

BZOJ2159 : Crash 的文明世界

$x^k=\sum_{i=1}^k Stirling2(k,i)\times i!\times C(x,i)$ 设$f[i][j]=\sum_{k=1}^n C(dist(i,k),j)$. 则可以利用$C(i,j)=C(i-1,j-1)+C(i-1,j)$,通过树形DP求出$f$. 时间复杂度$O((n+k)k)$. #include<cstdio> const int N=50010,M=155,P=10007; int n,k,i,j,x,y,S[M][M],fac[M],g[N],v[

[Lucas][树形dp][组合] Bzoj P2111 Perm 排列计数

Description 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值 题解 把i/2看作i和i+1的父亲,然后这样就会形成一棵完全二叉树 那么就可以考虑树形dp,设f[i]表示从i到n的方案数,size[i]表示第i个数的子树大小 那么如果i*2>n,那么f[i]=1,如果i*2==n,那么f[i]=f[i*2] 如果i*2+1&l

【BZOJ-3572】世界树 虚树 + 树形DP

3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status][Discuss] Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持续运转的根本基石.世界树的形态可以用一个数学模型来描述:世界树中有n个种族,种