zoukankan      html  css  js  c++  java
  • bzoj4313 三维积木

    传送门

    分析

    我们假设主视图的颜色为1

    如果只有两种颜色,且能求出w[x][y]表示一列中放置x个1和y个2的方案数

    则我们可用dp[i][j][k]表示考虑到第i列放j个1和k个2的方案数,这样的复杂度为$O(n^5)$

    我们可以把颜色2和颜色3统一看成颜色2,最后方案数乘上$C_{b+c}^b$即可

    于是我们考虑如何求出w[x][y]

    我们可以再将这两种颜色看为一种,设ddp[i][j]表示在这一列放i个积木,最高高度恰好为j的方案数

    不难得出

         w[x][y] = $sum_{i=1}^x$ddp[x+y][i] * $C_{x+y-i}^{x-i}$

    至于如何求ddp[i][j]我们可以再数组最后再加以为[0/1]表示是否出现过高度为j的情况

    用前缀和优化一下即可使求这个的过程变为$O(n^2)$

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    const int mod = 1e9+7;
    int w[110][110],ddp[110][110][2],dp[110][110][110],C[110][110];
    int pre[110][110][2];
    inline void getc(){
        int i,j,k;
        for(i=0;i<=100;i++)C[i][0]=C[i][i]=1;
        for(i=1;i<=100;i++)
          for(j=1;j<i;j++)
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    }
    int main(){
        int n,m,a,b,c,i,j,k,p,q,Ans=0;
        cin>>a>>b>>c>>n;
        m=max(a,max(b,c));
        getc();
        for(i=1;i<=m;i++)
          for(j=0;j<=2*m;j++)
            for(k=1;k<=i;k++){
              memset(ddp,0,sizeof(ddp));
              memset(pre,0,sizeof(pre));
              for(p=0;p<k;p++){
                 ddp[1][p][0]=1;
                 pre[1][p][0]=p+1;
              }
              for(p=k;p<=i+j;p++)pre[1][p][0]=pre[1][p-1][0];
              pre[1][k][1]=ddp[1][k][1]=1;
              for(p=k+1;p<=i+j;p++)pre[1][p][1]=pre[1][p-1][1];
              for(p=2;p<=n;p++)
                for(q=0;q<=i+j;q++){
                  ddp[p][q][1]=(pre[p-1][q][1]-(q-k-1>=0?pre[p-1][q-k-1][1]:0)
                     +(q-k>=0?ddp[p-1][q-k][0]:0))%mod;
                  if(ddp[p][q][1]<0)ddp[p][q][1]+=mod;
                  ddp[p][q][0]=(pre[p-1][q][0]-(q-k>=0?pre[p-1][q-k][0]:0))%mod;
                  if(ddp[p][q][0]<0)ddp[p][q][0]+=mod;
                  pre[p][q][1]=((q>0?pre[p][q-1][1]:0)+ddp[p][q][1])%mod;
                  pre[p][q][0]=((q>0?pre[p][q-1][0]:0)+ddp[p][q][0])%mod;
                } 
              w[i][j]=(w[i][j]+
                (long long)ddp[n][i+j][1]*C[i+j-k][i-k]%mod)%mod;
            }
        w[0][0]=1;
        dp[0][0][0]=1;
        for(i=1;i<=n;i++)
          for(j=0;j<=m;j++)
            for(k=0;k<=2*m;k++)
              for(p=0;p+j<=m;p++)
                for(q=0;q+k<=2*m;q++)
                  dp[i][j+p][k+q]=(dp[i][j+p][k+q]+
                    (long long)dp[i-1][j][k]*w[p][q]%mod)%mod;
        Ans=((long long)dp[n][a][b+c]*C[b+c][b]%mod
           +(long long)dp[n][b][a+c]*C[a+c][a]%mod
           +(long long)dp[n][c][b+a]*C[b+a][b]%mod)%mod;
        printf("%d
    ",Ans);
        return 0;
    }
  • 相关阅读:
    用PHP写一个代理来解决跨域问题
    curl
    centOS 安装及部署 SVN
    vue.js 安装
    谷歌开发者 代码调试同步本地文件功能
    Liunx 下的 SNMP 及 PHP如何连接
    2017年5月11日 开放大学 理财考试记
    js window.onlload 自遐想
    纯页面跳转问题
    mysql 字列问题
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10023569.html
Copyright © 2011-2022 走看看