码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3294: [Cqoi2011]放棋子

时间:2019-01-18 12:21:47      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:algo   space   没有   pac   iostream   --   def   zoj   const   

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

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

十种颜色难以状压,但是我们可以对于每种颜色,把它覆盖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\n",ans);
    
    return 0;
}

 


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

bzoj3294: [Cqoi2011]放棋子

标签:algo   space   没有   pac   iostream   --   def   zoj   const   

原文地址:https://www.cnblogs.com/AKCqhzdy/p/10286571.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!