【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
3294: [Cqoi2011]放棋子
Description
Input
输入第一行为两个整数n, m, c,即行数、列数和棋子的颜色数。第二行包含c个正整数,即每个颜色的棋子数。所有颜色的棋子总数保证不超过nm。
Output
输出仅一行,即方案总数除以 1,000,000,009的余数。
Sample Input
4 2 2
3 1Sample Output
8HINT
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+组合数学+容斥原理)的更多相关文章
- bzoj3294[Cqoi2011]放棋子 dp+组合+容斥
3294: [Cqoi2011]放棋子 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 755 Solved: 294[Submit][Status] ...
- [CQOI2011]放棋子--DP
题目描述: 输入格式 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数保证不超过nm.N,M<=30 C<=10 ...
- 【BZOJ 3294】[Cqoi2011]放棋子
题解: 一道很经典的组合数+dp 首先考虑f[i][j][k]表示前k种颜色正好占据了i行j列 转移的话就是枚举第k种颜色占据了几行几列 通过自身转移 然后其在内部的相对顺序是不确定的所以要乘以组合数 ...
- BZOJ 3294: [Cqoi2011]放棋子
3294: [Cqoi2011]放棋子 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 628 Solved: 238[Submit][Status] ...
- bzoj千题计划261:bzoj3294: [Cqoi2011]放棋子
http://www.lydsy.com/JudgeOnline/problem.php?id=3294 如果一个颜色的棋子放在了第i行第j列,那这种颜色就会占据第i行第j列,其他颜色不能往这儿放 设 ...
- [CQOI2011]放棋子 (DP,数论)
[CQOI2011]放棋子 \(solution:\) 看到这道题我们首先就应该想到有可能是DP和数论,因为题目已经很有特性了(首先题面是放棋子)(然后这一题方案数很多要取模)(而且这一题的数据范围很 ...
- P3158 [CQOI2011]放棋子(dp+组合数)
P3158 [CQOI2011]放棋子 放棋子的顺序和方案数无关,所以可以从按颜色递推 设$f[u][p][k]$为放到第$u$种颜色,所剩空间$p*k$的方案数 $g[u][i][j]$表示第$u$ ...
- [洛谷P3158] [CQOI2011]放棋子
洛谷题目链接:[CQOI2011]放棋子 题目描述 在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同 颜色的棋子不能在同一行或者同一列.有多少祌方法?例如,n=m=3,有两个 ...
- BZOJ3294: [Cqoi2011]放棋子
Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数保证不超过nm. Output 输出 ...
随机推荐
- (64位)本体学习程序(ontoEnrich)系统配置说明文档
1系统环境 64位 Ubuntu 2 第三方依赖库配置 boost_1_44_0 #解压boost_1_44_0.tar.gz 到 /usr/local.如果出现权限问题,请用sudo执行该命令 ta ...
- ClassNotFoundException:com.sun.xml.bind.v2.ContextFactory
项目中引入hive-jdbc-1.2.1-standalone.jar包之后,报错如下: Caused by: javax.xml.bind.JAXBException: Provider com.s ...
- Map集合的两种取出方式
Map集合有两种取出方式, 1.keySet:将Map中的键存入Set集合,利用set的迭代器来处理所有的键 举例代码如下: import java.util.*; class Test { publ ...
- Java并发编程学习路线
一年前由于工作需要从微软技术栈入坑Java,并陆陆续续做了一个Java后台项目,目前在搞Scala+Java混合的后台开发,一直觉得并发编程是所有后台工程师的基本功,所以也学习了小一年Java的并发工 ...
- 面试C++失败
到今天,面试已经整整一周,一个offer没有收到,mmp. 无奈,痛苦,迷茫. 以前活的太安逸,太舒适了. 自以为是,异想天开. 要重新振作起来. 要不断学习,保持强大,未来之路才会越走越宽.
- 简单漂亮的php验证码函数
/* *说明:函数功能是生成验证码 * 参数说明:输入 长度,宽度,高度 */ function vcode($_code_length = , $_width = , $_height = ){ $ ...
- android内存回收顺序
最近做项目的时候,经常会考虑到系统回收进程,释放资源等问题.特别查找了相关资料,了解下android内存回收顺序以及回收场景. 下面内容都为网络查找资料,若有错误,欢迎指出. 以下顺序,依次被回收的可 ...
- 2-Python基础语法-内存管理-运算符-程序控制
目录 1 Python 基础语法 1.1 注释 1.2 缩进 1.3 续行 1.4 标识符 1.5 转义序列 1.6 数字 1.7 字符串 1.8 其他 2 Python 运算符 2.1 赋值运算符 ...
- Elasticsearch5.0 安装问题集锦【转】
转自 Elasticsearch5.0 安装问题集锦 - 代码&优雅着&生活 - 博客园http://www.cnblogs.com/sloveling/p/elasticsearch ...
- iTextSharp之pdfRead(两个文件文本内容的比较,指定页数的pdf截取,水印的添加)
using iTextSharp.text; using iTextSharp.text.pdf; using iTextSharp.text.pdf.parser; using System; us ...