zoukankan      html  css  js  c++  java
  • bzoj3294: [Cqoi2011]放棋子

    明显的,行列的顺序是没有关系的

    我们可以考虑用几个块+组合顺序把答案拼出来

    十种颜色难以状压,但是我们可以对于每种颜色,把它覆盖i行j列的方案数给算出来

    LL g[maxC][maxl][maxl];//用cn[i]个棋子占i行j列并且一定占满 ------> 的方案数

    LL f[maxC][maxl][maxl];//前c种棋子占i行j列 -----> 的方案数

    这样上一个二维的背包,每次弄一个组合数算一下行插在那,列插在那就完了

    现在讨论一下g怎么求,我们需要容斥一下

    可以用总的方案数-有某些行或某些列没被覆盖的方案数

    总的:有i*j个坑可以填

    再减去u<=i,v<=j 却也用够了cn[i]的方案,它也有多种组合方式

    具体见代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int maxl=33;
    const int maxC=13,sumC=1100;
    const LL mod=1e9+9;
    LL C[maxl*maxl][maxl*maxl];
    void initC()
    {
        C[0][0]=1;
        for(int i=1;i<maxl*maxl;i++)
        {
            C[i][0]=1;
            for(int j=1;j<maxl*maxl;j++)
                C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
    }
    //~~~~~~~~~~~init~~~~~~~~~~~~~~~~
    
    LL g[maxC][maxl][maxl];//用cn[i]个棋子占i行j列并且一定占满 ------> 的方案数 
    LL f[maxC][maxl][maxl];//前c种棋子占i行j列 -----> 的方案数 
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        initC();
        int n,m,CC;
        scanf("%d%d%d",&n,&m,&CC);
        for(int t=1;t<=CC;t++)
        {
            int c;
            scanf("%d",&c);
            for(int i=0;i<=n;i++)
                for(int j=0;j<=m;j++)
                {
                    g[t][i][j]=C[i*j][c];
                    for(int u=0;u<=i;u++)
                        for(int v=0;v<=j;v++)
                        {
                            if(u==i&&v==j)continue;
                            g[t][i][j]=(g[t][i][j]-g[t][u][v]*C[i][u]*C[j][v])%mod;
                        }
                    g[t][i][j]=(g[t][i][j]+mod)%mod;
                }
        }
        
        f[0][0][0]=1;
        for(int t=1;t<=CC;t++)
            for(int i=0;i<=n;i++)
                for(int j=0;j<=m;j++)
                    for(int u=0;u+i<=n;u++)    
                        for(int v=0;v+j<=m;v++)
                            f[t][i+u][j+v]+=f[t-1][i][j]*g[t][u][v]%mod*C[n-i][u]%mod*C[m-j][v]%mod;
        LL ans=0;
        for(int i=0;i<=n;i++) 
            for(int j=0;j<=m;j++)
                ans=(ans+f[CC][i][j])%mod;
        printf("%lld
    ",ans);
        
        return 0;
    }


    LL g[maxC][maxl][maxl];//用cn[i]个棋子占i行j列并且一定占满 ------> 的方案数 LL f[maxC][maxl][maxl];//前c种棋子占i行j列 -----> 的方案数 

  • 相关阅读:
    ArcEngine 地图与布局的联动
    ArcGIS Server安装篇
    AO+C#设置栅格图层基高 制作三维
    ArcGIS 10研究(一) 之 Desktop总体介绍 转载
    linux centos7 增加硬盘
    linux CentOS7安装oracle12c
    java中关于Socket类通信的基本测试程序
    Ubuntu 的中国梦
    我们无需“开始”菜单
    数据库战略高度解析 之系列说明
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10286571.html
Copyright © 2011-2022 走看看