zoukankan      html  css  js  c++  java
  • 【BZOJ2159】Crash的文明世界 【斯特林数】【树形dp】

    题目传送门
    题意:求对于每个i的j=1ndis(i,j)k
    这里有一个公式:xk=i=1xS(k,i)Axi。S是第二类斯特林数,A是排列数。
    其实这个式子的组合意义就是把k个球放进x个盒子的方案数。右边的意思是枚举有哪些盒子要放球,选球的方案数乘上选盒子的方案数。
    这个是不好统计的,我们把它变一下:xk=i=1xS(k,i)i!Cxi
    于是我们令f[i][j]=k=1nC(dis(i,k),j),通过两次树形dp求出f数组,最后再统计一下即可。具体方法详见代码。

    常数极大的代码

    #include<cstdio>
    typedef int ll;
    const int N=50005,M=155;
    const ll mod=10007;
    int n,k,u,v,cnt,head[N],to[N*2],nxt[N*2];
    ll ans,f[N][M][2],jc[M],s[M][M];
    void adde(int u,int v){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    void dfs1(int pre,int u){
        f[u][0][0]=1;
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=pre){
                dfs1(u,v);
                f[u][0][0]=(f[u][0][0]+f[v][0][0])%mod;
                for(int j=1;j<=k;j++){
                    f[u][j][0]=(f[u][j][0]+f[v][j-1][0]+f[v][j][0])%mod;
                }
            }
        }
    }
    void dfs2(int pre,int u){
        if(pre){
            f[u][0][1]=(n-f[u][0][0]+mod)%mod;
            for(int i=1;i<=k;i++){
                f[u][i][1]=(f[u][i][1]+f[pre][i][0]+f[pre][i-1][0]+f[pre][i-1][1]+f[pre][i][1])%mod;
                f[u][i][1]=((f[u][i][1]-f[u][i][0]-2*f[u][i-1][0])%mod+mod)%mod;
                if(i>1){
                    f[u][i][1]=(f[u][i][1]-f[u][i-2][0]+mod)%mod;
                }
            }
        }
        int v;
        for(int i=head[u];i;i=nxt[i]){
            v=to[i];
            if(v!=pre){
                dfs2(u,v);
            }
        }
    }
    int main(){
        int L,now,A,B,Q,tmp;
        scanf("%d%d%d",&n,&k,&L); 
        scanf("%d%d%d%d",&now,&A,&B,&Q); 
        for (int i=1;i<n;i++){ 
            now=(now*A+B)%Q;
            tmp=(i<L)?i:L;
            u=i-now%tmp;
            v=i+1;
            adde(u,v);
            adde(v,u);
        }
    /*  scanf("%d%d",&n,&k);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }*/
        dfs1(0,1);
        dfs2(0,1);
        jc[0]=s[0][0]=1;
        for(int i=1;i<=k;i++){
            jc[i]=i*jc[i-1]%mod;
            for(int j=1;j<=k;j++){
                s[i][j]=(s[i-1][j-1]+j*s[i-1][j])%mod;
            }
        }
        for(int i=1;i<=n;i++){
            ans=0;
            for(int j=1;j<=k;j++){
                ans=(ans+1LL*s[k][j]*jc[j]%mod*(f[i][j][0]+f[i][j][1])%mod)%mod;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Junit使用教程(四)
    《数据通信与网络》笔记--TCP中的拥塞控制
    Android Apps开发环境搭建
    quick-cocos2d-x教程10:实现血条效果。
    spring实战笔记6---springMVC的请求过程
    LINQ体验(1)——Visual Studio 2008新特性
    eclipse maven 插件的安装和配置
    [LeetCode][Java] Remove Duplicates from Sorted List II
    C++对象模型——解构语意学(第五章)
    SQL SERVER之数据查询
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476870.html
Copyright © 2011-2022 走看看