Luogu4827 Crash的文明世界

Luogu4827 Crash的文明世界

题面:Luogu

解析

很久以前做的题了,今天重新推一遍。

\[S(i)=\sum_{j=1}^{n} dist(i,j)^k\]

\[=\sum_{j=1}^{n} \sum_{t=0}^{k} S(k,t) \times t! \times { dist(i,j) \choose t }\]

\[=\sum_{t=0}^{k} S(k,t) \times t! \times \sum_{j=1}^{n} { dist(i,j) \choose t}\]

设$f(i,j)=\sum_{k=1}^{n} { dist(i,k) \choose j } \(,那么\)S(i)=\sum_{t=0}^{k} S(k,t) \times t! \times f(i,t)\(,现在考虑如何求\)f(i,j)$。

观察到有\({dist(i,j) \choose k}={dist(i,j)-1 \choose k-1}+{dist(i,j)-1 \choose k}\)
这启迪我们对于一个点,可以先计算子树内的贡献。
不妨设\(g_1(i,j)\)表示子树内的贡献,\(g_2(i,j)\)表示子树外的贡献,
由上式知\(g_1(i,j)=\sum_{v \subseteq i.son} g_1(v,j-1)+g_1(v,j)(j\gt0)\)
这样我们就计算了子树内的贡献。
那么如何解决子树外的贡献呢?
仍然利用上面的思路,从上往下计算,
\(tmp(v,j)=g_1(u,j)-g_1(v,j)-g_1(v,j-1)\)
那么有\(g_2(v,j)=tmp(v,j)+tmp(v,j-1)+g_2(u,j-1)+g_2(u,j)\)
最后即可\(O(nk)\)得到\(f(i,j)\)

代码


// luogu-judger-enable-o2
#include<cstdio>
#define N 50005

using namespace std;

const int P=1e4+7;

inline int In(){
    char c=getchar(); int x=0,ft=1;
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
    for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
    return x*ft;
}

int n,K,h[N],e_tot=0,ans;
struct E{ int to,nex; }e[N<<1];

inline void add(int u,int v){
    e[++e_tot]=(E){v,h[u]}; h[u]=e_tot;
}

int S[155][155],fac[155];

inline void Get_S_fac(){
    fac[0]=1; for(int i=1;i<=K;++i) fac[i]=1ll*i*fac[i-1]%P;
    S[0][0]=1;
    for(int i=1;i<=K;++i)
    for(int j=1;j<=K;++j)
    S[i][j]=(S[i-1][j-1]+1ll*j*S[i-1][j]%P)%P;
}

int g1[N][155],g2[N][155],tmp[155];

void dfs1(int u,int pre){
    g1[u][0]=1;
    for(int i=h[u],v;i;i=e[i].nex){
        if((v=e[i].to)==pre) continue; dfs1(v,u);
        g1[u][0]=(g1[u][0]+g1[v][0])%P;
        for(int j=1;j<=K;++j)
        g1[u][j]=(g1[u][j]+(g1[v][j-1]+g1[v][j])%P)%P;
    }
}

void dfs2(int u,int pre){
    for(int i=h[u],v;i;i=e[i].nex){
        if((v=e[i].to)==pre) continue;
        tmp[0]=(g1[u][0]-g1[v][0]+P)%P;
        for(int j=1;j<=K;++j)
        tmp[j]=((g1[u][j]-g1[v][j-1]+P)%P-g1[v][j]+P)%P;
        g2[v][0]=tmp[0];
        for(int j=1;j<=K;++j) g2[v][j]=(tmp[j-1]+tmp[j])%P;
        g2[v][0]=(g2[u][0]+g2[v][0])%P;
        for(int j=1;j<=K;++j)
        g2[v][j]=(g2[v][j]+(g2[u][j-1]+g2[u][j])%P)%P;
        dfs2(v,u);
    }
}

int main(){
    n=In(); K=In(); Get_S_fac();
    for(int i=1,u,v;i<n;++i){
        u=In(); v=In();
        add(u,v); add(v,u);
    }
    dfs1(1,-1); dfs2(1,-1);
    for(int i=1;i<=n;++i){
        ans=0;
        for(int t=0;t<=K;++t)
        ans=(ans+1ll*(g1[i][t]+g2[i][t])%P*S[K][t]*fac[t]%P)%P;
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/pkh68/p/10684710.html