• 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) imes t! imes { dist(i,j) choose t } ]

    [=sum_{t=0}^{k} S(k,t) imes t! imes 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) imes t! imes 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)(jgt0))
    这样我们就计算了子树内的贡献。
    那么如何解决子树外的贡献呢?
    仍然利用上面的思路,从上往下计算,
    (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
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    [GUIDE] How to Setup Ubuntu 16.04 LTS Xenial Xerus for Compiling Android ROMs
    设置Ubuntu 16.04 LTS的Unity启动器的位置命令
    sed系列:行或者模式匹配删除特定行
    HDOJ 4923 Room and Moor
    Office365client通过本地方式批量部署(即点即用部署)
    hdu 1867 A + B for you again
    Photoshop经常使用快捷键(2)
    SQL_为表和列加凝视
    从头认识java-17.5 堵塞队列(以生产者消费者模式为例)
    Unity5 怎样做资源管理和增量更新
  • 原文地址:https://www.cnblogs.com/pkh68/p/10684710.html
Copyright © 2020-2023  润新知