zoukankan      html  css  js  c++  java
  • ZCC loves cube(cube)

    题目描述

     

    调戏完了狗,ZCC开始玩起了积木。ZCC的面前有一块n*n的棋盘,他要用这些1*1*1的积木在棋盘上搭出一个宏伟的建筑。积木有三种颜色,ZCC认为一个建筑要被称为宏伟的应该满足能从正面看到的每一个积木都是同一种颜色。现在,ZCC想要知道他能用他拥有的积木搭出多少种宏伟的建筑。当然,为了让建筑足够大,ZCC需要用完他所有的积木。两个建筑被称为不同的当且仅当两个建筑形状不同或者存在一块相同位置不同颜色的积木。

     

     

    输入

     

    包含四个数n,r,g,b 。表示棋盘大小,红色积木个数,绿色积木个数,蓝色积木个数。

     

     

    输出

     

    包含一个数,表示方案数,对10^9+7取模。

     

    数据规模与约定

    对于10%的数据,n,r≤40 ,g,b=0

    对于另外20%的数据,n,r,g,b≤4

    对于100% 的数据,n,r,g,b≤30


    solution

    计数类问题,考虑dp

    由于每一列互不影响,我们分开做。

    先考虑一列,不考虑颜色

    f[i][j][k] 表示前i位,之前最大值为j,放k个木块的方案数

    f[i][j][k]= sum_{x=1}^{j} f[i-1][j][k-x]+ sum_{y=1}^{j} f[i-1][y][j];

    再令g[i][j][k]表示前i列用了k块,主视图面积为j的方案数

    g[i][j][k]=g[i-1][j-x][k-y]*f[n][x][y]

    然后根据面积填颜色

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define mod 1000000007
    using namespace std;
    int n,a,b,c,S,M,tot;
    ll f[45][45][166],g[45][125][125],ans,tmp;
    ll h[80005],ny[80005];
    ll F(ll a,int num){
        ll cnt=1;
        while(num){
            if(num&1)cnt=cnt*a;
            a=a*a%mod;cnt%=mod;num>>=1;
        }
        return cnt;
    }
    void getC(){
        int o=n*n*n;h[0]=1;
        for(int i=1;i<=o;i++)h[i]=h[i-1]*i%mod;
        ny[o]=F(h[o],mod-2);
        for(int i=o-1;i>=0;i--)ny[i]=ny[i+1]*(i+1)%mod;
    }
    ll C(int N,int M){
        return (h[N]*ny[M]%mod)*ny[N-M]%mod;
    }
     
    int main()
    {
        cin>>n>>a>>b>>c;S=a+b+c;M=max(a,max(b,c));
        f[0][0][0]=1;
        for(int i=1;i<=n;i++){
            f[i][0][0]=1;
            for(int j=1;j<=M;j++){//M
                for(int k=j;k<=S;k++){
                    for(int x=0;x<=j;x++)
                    f[i][j][k]=(f[i][j][k]+f[i-1][j][k-x])%mod;
                    for(int x=0;x<j;x++)
                    f[i][j][k]=(f[i][j][k]+f[i-1][x][k-j])%mod;
                    //cout<<"i "<<i<<' '<<"j "<<j<<' '<<"k "<<k<<' '<<f[i][j][k]<<endl;
                }
            }
        }
        //
        g[0][0][0]=1;
        for(int i=1;i<=n;i++){
            g[i][0][0]=1;
            for(int j=1;j<=S;j++){
                for(int k=j;k<=S;k++){
                    for(int x=0;x<=j;x++)
                    for(int y=x;y<=k;y++){
                        g[i][j][k]=g[i][j][k]+g[i-1][j-x][k-y]*f[n][x][y]%mod;
                        g[i][j][k]%=mod;
                    }//cout<<"i "<<i<<' '<<"j "<<j<<' '<<"k "<<k<<' '<<g[i][j][k]<<endl;
                }
            }
        }
        //for(int i=0;i<=S;i++)cout<<g[n][i][S]<<endl;
        getC();
        for(int i=1;i<=S;i++){
            if(a>=i){
                int ns=S-i;
                ll tmp=g[n][i][S];
                tmp=tmp*C(ns,b)%mod*C(ns-b,c)%mod;
                ans=(ans+tmp)%mod;
            }
            if(b>=i){
                int ns=S-i;
                ll tmp=g[n][i][S];
                tmp=tmp*C(ns,a)%mod*C(ns-a,c)%mod;
                ans=(ans+tmp)%mod;
            }
            if(c>=i){
                int ns=S-i;
                ll tmp=g[n][i][S];
                tmp=tmp*C(ns,a)%mod*C(ns-a,b)%mod;
                ans=(ans+tmp)%mod;
            }
        }
        cout<<ans<<endl;
        //cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    为什么DIY报价----走出软件作坊:三五个人十来条枪 如何成为开发正规军(十二)[转]
    物以类聚,人以群分--走出软件作坊:三五个人十来条枪 如何成为开发正规军(十一)[转]
    将服务费用DIY到底----走出软件作坊:三五个人十来条枪 如何成为开发正规军(十)[转]
    实施费用也能DIY--走出软件作坊:三五个人十来条枪 如何成为开发正规军(九)[转]
    去掉iphone手机滑动默认行为
    获取json对象长度的问题
    手机淘宝用JS来动态写meta标签(1像素边框处理方法)
    移动端多行文字截断
    移动端初始化页面
    JavaScript 高级程序设计 02-变量、数据类型
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358749.html
Copyright © 2011-2022 走看看