3294: [Cqoi2011]放棋子

Description

Input

输入第一行为两个整数nmc,即行数、列数和棋子的颜色数。第二行包含c个正整数,即每个颜色的棋子数。所有颜色的棋子总数保证不超过nm

Output

输出仅一行,即方案总数除以 1,000,000,009的余数。

Sample Input

4 2 2
3 1

Sample Output

8

HINT

N,M<=30 C<=10 总棋子数<=250

Source

【分析】

  表示一开始看错题ORZ。。以为相同颜色的不能放一起【这样怎么做??

  然后就是其实题目不是这样的、、、

  DP[i][j][k]表示决策到第k种颜色,前k种颜色一共占了i行j列的方案数。

  枚举第k行占的行数和列数,ii,jj,那么dp[i][j][k]=f[i-ii][j-jj][k-1]*B[ii][jj][k]*C[n-(i-ii)][ii]*C[m-(j-jj)][jj]

  其中C是组合数,B[ii][jj][k]表示用ii行jj列填k个东西的方案(注意B数组要满足每一行每一列都有东西,不然好像很容易算重复)

  对于B数组,我一开始用了两种方法求,都不对(超容易算重复smg,然后很内伤)

  最后感觉只有枚举这一种方法是可以求出来的,

  就是递推 B[x][y][z]=C[x*y][k]-sigma(B[i][j][k]*C[x][i]*C[y][j]) (1<=i<=x&&1<=j<=y&&(i!=x||j!=y))

  【这里是容斥吧?

  组合数学没学好所以我这题又做了很久ORZ。。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Mod 1000000009
#define Maxn 910
#define LL long long LL sm[],f[][][];
int n,m,c; LL C[Maxn][Maxn]; void get_c()
{
memset(C,,sizeof(C));
for(int i=;i<=n*m;i++) C[i][]=;
for(int i=;i<=n*m;i++)
for(int j=;j<=i;j++) C[i][j]=(C[i-][j-]+C[i-][j])%Mod;
} LL B[][][];
LL get_B(int x,int y,int z)
{
if(B[x][y][z]!=-) return B[x][y][z];
if(x==&&sm[z]==) {B[x][y][z]=;return ;}
if(sm[z]<x||sm[z]<y||x*y<sm[z]) {B[x][y][z]=;return ;}
LL ans=;
ans=C[x*y][sm[z]];
for(int i=;i<=x;i++)
for(int j=;j<=y;j++)
{
if(i==x&&j==y) continue;
// ans++;
LL X=get_B(i,j,z)%Mod,
Y=(C[x][i]*C[y][j])%Mod;
ans=ans-X*Y;ans%=Mod;
ans=(ans+Mod)%Mod;
}
// printf("B[%d][%d][%d]=%d\n",x,y,z,ans);
/*for(int i=1;i<=z;i++)
ans=(ans+get_B(x-1,y,z-i)*C[y][i])%Mod;
printf("B[%d][%d][%d]=%d\n",x,y,z,ans);*/ /*ans=C[n*m][x];ans%=Mod;
ans-=C[(n-1)*m][x]*n;ans%=Mod;
ans-=C[n*(m-1)][x]*m;ans%=Mod;
ans+=C[(n-1)*(m-1)][x]*n*m;ans%=Mod;
ans=(ans+Mod)%Mod;*/
B[x][y][z]=ans;
return ans;
} int main()
{
scanf("%d%d%d",&n,&m,&c);
for(int i=;i<=c;i++) scanf("%d",&sm[i]);
get_c();
memset(f,,sizeof(f));
memset(B,-,sizeof(B));
f[][][]=;
LL ans=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=;k<=c;k++) get_B(i,j,k);
for(int k=;k<=c;k++)
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
for(int ii=;ii<=i;ii++)
for(int jj=;jj<=j;jj++)
{
LL X=(C[n-(i-ii)][ii]*C[m-(j-jj)][jj])%Mod,
Y=(f[i-ii][j-jj][k-]*B[ii][jj][k])%Mod;
f[i][j][k]=(f[i][j][k]+X*Y)%Mod;
} // f[i][j][k]=(f[i][j][k]+(C[n-(i-ii)][ii]*C[m-(j-jj)][jj])%Mod*(f[i-ii][j-jj][k-1]*C[ii*jj][sm[k]])%Mod)%Mod;
if(k==c) ans=(ans+f[i][j][k])%Mod;
// printf("f[%d][%d][%d]=%lld\n",i,j,k,f[i][j][k]);
}
}
printf("%lld\n",ans);
return ;
}

屏蔽掉的是一开始两种错误方法。。

2017-03-21 08:28:26

【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)的更多相关文章

  1. bzoj3294[Cqoi2011]放棋子 dp+组合+容斥

    3294: [Cqoi2011]放棋子 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 755  Solved: 294[Submit][Status] ...

  2. [CQOI2011]放棋子--DP

    题目描述: 输入格式 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数保证不超过nm.N,M<=30 C<=10 ...

  3. 【BZOJ 3294】[Cqoi2011]放棋子

    题解: 一道很经典的组合数+dp 首先考虑f[i][j][k]表示前k种颜色正好占据了i行j列 转移的话就是枚举第k种颜色占据了几行几列 通过自身转移 然后其在内部的相对顺序是不确定的所以要乘以组合数 ...

  4. BZOJ 3294: [Cqoi2011]放棋子

    3294: [Cqoi2011]放棋子 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 628  Solved: 238[Submit][Status] ...

  5. bzoj千题计划261:bzoj3294: [Cqoi2011]放棋子

    http://www.lydsy.com/JudgeOnline/problem.php?id=3294 如果一个颜色的棋子放在了第i行第j列,那这种颜色就会占据第i行第j列,其他颜色不能往这儿放 设 ...

  6. [CQOI2011]放棋子 (DP,数论)

    [CQOI2011]放棋子 \(solution:\) 看到这道题我们首先就应该想到有可能是DP和数论,因为题目已经很有特性了(首先题面是放棋子)(然后这一题方案数很多要取模)(而且这一题的数据范围很 ...

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

    P3158 [CQOI2011]放棋子 放棋子的顺序和方案数无关,所以可以从按颜色递推 设$f[u][p][k]$为放到第$u$种颜色,所剩空间$p*k$的方案数 $g[u][i][j]$表示第$u$ ...

  8. [洛谷P3158] [CQOI2011]放棋子

    洛谷题目链接:[CQOI2011]放棋子 题目描述 在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同 颜色的棋子不能在同一行或者同一列.有多少祌方法?例如,n=m=3,有两个 ...

  9. BZOJ3294: [Cqoi2011]放棋子

    Description   Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数保证不超过nm. Output 输出 ...

随机推荐

  1. 【BZOJ】1355 [Baltic2009]Radio Transmission

    [算法]KMP [题解]KMP中n-next[n]得到最小循环节的性质. 考虑一个循环串(最后一个循环节可能残缺),它最长的[后缀=前缀]一定是以第二个循环节为起始位置的后缀. 正着考虑的话假设后缀T ...

  2. 使用generatorConfig工具自动生成mybatis的实体类以及dao接口和映射文件

    1:数据准备 创建一个数据库表 CREATE TABLE `logininfo` ( `id` ) NOT NULL AUTO_INCREMENT, `username` ) DEFAULT NULL ...

  3. 爬虫--Scrapy之Downloader Middleware

    下载器中间件(Downloader Middleware) 下载器中间件是介于Scrapy的request/response处理的钩子框架. 是用于全局修改Scrapy request和respons ...

  4. 安装node-sass的正确姿势【转】

    安装 node-sass 的时候总是会各种不成功,今天我琢磨了一会儿总算知道要怎么解决了. 首先要知道的是,安装 node-sass 时在 node scripts/install 阶段会从 gith ...

  5. RTM,RTW,GA等软件版本号详解

    一直以来,对于新手而言,软件的版本号都是个比较困扰人的问题,什么Beta.RC,再来个RTM.RTW....头大了吧?RTM和RTW有什么区别?借此机会,就给大家介绍一下这方面的小知识吧. 1.软件开 ...

  6. python基础之常用的高阶函数

    前言 高阶函数指的是能接收函数作为参数的函数或类:python中有一些内置的高阶函数,在某些场合使用可以提高代码的效率. map() map函数可以把一个迭代对象转换成另一个可迭代对象,不过在pyth ...

  7. 2016 ACM ICPC Asia Region - Tehran

    2016 ACM ICPC Asia Region - Tehran A - Tax 题目描述:算税. solution 模拟. B - Key Maker 题目描述:给出\(n\)个序列,给定一个序 ...

  8. WPF之DataGrid--列的前台及后台实现

    一.前台实现 在xaml里可以很轻松地实现一个如下图所示的DataGrid <StackPanel> <ComboBox Width="50" Horizonta ...

  9. Retrofit:类型安全的REST客户端for 安卓&Java

    Retrofit:类型安全的REST客户端for 安卓&Java 2014年5月5日 星期一 21:11 官网:  http://square.github.io/retrofit/ GitH ...

  10. JavaScript基础练习(一)

    加法的案例改为 可以做加减乘除.求余五种运算 为抵抗洪水,战士连续作战89小时,编程计算共多少天零多少小时? (function(a){ alert("战士连续作战"+parseI ...