bzoj3294: [Cqoi2011]放棋子

Posted akcqhzdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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列 -----> 的方案数 

以上是关于bzoj3294: [Cqoi2011]放棋子的主要内容,如果未能解决你的问题,请参考以下文章

[CQOI2011]放棋子

[CQOI2011]放棋子

[CQOI2011] 放棋子 - 计数dp

P3158 [CQOI2011]放棋子(dp+组合数)

[题解] [CQOI2011] 放棋子

luogu 3158 [CQOI2011]放棋子