[CQOI2011]放棋子--DP
题目描述:
输入格式
输入第一行为两个整数n, m, c,即行数、列数和棋子的颜色数。
第二行包含c个正整数,即每个颜色的棋子数。
所有颜色的棋子总数保证不超过nm。
N,M<=30 C<=10 总棋子数有大于250的情况
输出格式
输出仅一行,即方案总数除以 1,000,000,009的余数。
样例
样例输入
4 2 2
3 1
样例输出
8
数据范围与提示
30% n,m<=10
solution:10%:cout<<0<<endl;
肯定有0的情况比如c>min(n,m)之类的。。。
20%:搜索,枚举所有状态。
据说这是搜索最高得分,然而博主考试时只拿到10分,而且还不是TLE。
下面说正解
我们考虑dp,设f[i][j][k]表示前k种颜色的棋子占领任意i行j列的方案数,g[i][j][k]表示第k种颜色的所有棋子占领任意i行j列的方案数;
那么我们首先可以得到g[i][j][k]=$C_{i*j}^{num[k]}$-$\sum_\limits{p=1}^{i}$$\sum_\limits{q=1}^{j}$g[p][q][k]*$C_{i}^{p}$*$C_{j}^{q}$
其实就是用合法的减去不合法的(实际上有没有被占领的行或列的方案数)
接下来得到f的方程:
$f[i][j][k]=\sum_{p=0}^{i-1}\sum_{q=0}^{j-1}$
$f[i][j][k]=\sum_{p=0}^{i-1}\sum_{q=0}^{j-1}f[p][q][k-1]*g[i-p][j-q][k]*C_{n-p}^{i-p}*C_{m-q}^{j-q}$,f[0][0][0]=1;
p,q,k-1就是枚举的上一个状态,$C_{n-p}^{i-p}$表示n-p行中选出i-p行放棋子,$C_{m-q}^{i-q}$同理,
最后ans=$\sum_{i=1}^{n}$$\sum_{j=1}^{m}$f[i][j][c],于是这道题就完美地解决了
放代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000009
#define ll long long
#define MAXNM 905
using namespace std;
int n,m,c,num[];
ll C[MAXNM][MAXNM],g[][][],f[][][],ans=;
int main(){
scanf("%d%d%d",&n,&m,&c);
for(int i=;i<=n*m;i++){
C[i][]=;
for(int j=;j<=i;j++)
C[i][j]=(C[i-][j]+C[i-][j-])%mod;
}
f[][][]=;
for(int k=;k<=c;k++)
scanf("%d",&num[k]);
for(int k=;k<=c;k++){
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
if(i*j<num[k]) continue;
g[i][j][k]=C[i*j][num[k]];
for(int p=;p<=i;p++)
for(int q=;q<=j;q++){
if(p<i||q<j)
g[i][j][k]=(g[i][j][k]-g[p][q][k]*C[i][p]%mod*C[j][q]%mod)%mod;
//cout<<g[i][j]<<endl;
}
}
}
for(int k=;k<=c;k++){
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int p=;p<i;p++)
for(int q=;q<j;q++){
int l=i-p,r=j-q;
if(l*r<num[k]) continue;
f[i][j][k]=(f[i][j][k]+f[p][q][k-]*g[l][r][k]%mod*C[n-p][l]%mod*C[m-q][r]%mod)%mod;
//cout<<f[i][j][k]<<endl;
}
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
ans=(ans+f[i][j][c])%mod;
printf("%lld\n",ans);
return ;
}
我们发现g只对当前一种棋子有贡献,所以第三维可以干掉,在每次输入时处理g和f
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000009
#define ll long long
#define MAXNM 905
using namespace std;
int n,m,c,num[12];
ll C[MAXNM][MAXNM],g[35][35],f[35][35][15],ans=0;
int main(){
scanf("%d%d%d",&n,&m,&c);
for(int i=0;i<=n*m;i++){
C[i][0]=1;
for(int j=1;j<=i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
f[0][0][0]=1;
for(int k=1;k<=c;k++){
scanf("%d",&num[k]);
memset(g,0,sizeof(g));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(i*j<num[k]) continue;
g[i][j]=C[i*j][num[k]];
for(int p=1;p<=i;p++)
for(int q=1;q<=j;q++){
if(p<i||q<j)
g[i][j]=(g[i][j]-g[p][q]*C[i][p]%mod*C[j][q]%mod)%mod;
//cout<<g[i][j]<<endl;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int p=0;p<i;p++)
for(int q=0;q<j;q++){
int l=i-p,r=j-q;
if(l*r<num[k]) continue;
f[i][j][k]=(f[i][j][k]+f[p][q][k-1]*g[l][r]%mod*C[n-p][l]%mod*C[m-q][r]%mod)%mod;
//cout<<f[i][j][k]<<endl;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=(ans+f[i][j][c])%mod;
printf("%lld\n",ans);
return 0;
}
[CQOI2011]放棋子--DP的更多相关文章
- bzoj3294[Cqoi2011]放棋子 dp+组合+容斥
3294: [Cqoi2011]放棋子 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 755 Solved: 294[Submit][Status] ...
- [CQOI2011]放棋子 (DP,数论)
[CQOI2011]放棋子 \(solution:\) 看到这道题我们首先就应该想到有可能是DP和数论,因为题目已经很有特性了(首先题面是放棋子)(然后这一题方案数很多要取模)(而且这一题的数据范围很 ...
- 【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
3294: [Cqoi2011]放棋子 Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数 ...
- 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,有两个 ...
- 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列,其他颜色不能往这儿放 设 ...
- BZOJ3294: [Cqoi2011]放棋子
Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数保证不超过nm. Output 输出 ...
- BZOJ3294: [Cqoi2011]放棋子(计数Dp,组合数学)
题目链接 解题思路: 发现一个性质,如果考虑一个合法的方案可以将行和列都压到一起,也就是说,在占用行数和列数一定的情况下,行列互换是不会影响答案的,那么考虑使用如下方程: $f[i][j][k]$为占 ...
随机推荐
- matplotlib实现伪彩色图像和色度条的展现
灰度图显示为伪彩色图 法一 import matplotlib.pyplot as plt img = plt.imread('C:/Users/leex/Desktop/lena.jpg') img ...
- 8-5接口测试用例设计与编写2 rest-assured
rest-assured 简约的接口测试DSL 支持xml json的结构化解析 支持xpath jsonpath gpath等多种解析方式 对Spring的支持比较前面 底层是httpclient ...
- Windows 获取控制台窗口句柄
详细信息 因为多个窗口可能具有相同的标题,您应该更改当前的控制台窗口标题为唯一的标题.这将有助于防止返回不正确的窗口句柄.使用 SetConsoleTitle() 来更改当前的控制台窗口标题.下面是此 ...
- php curl的正确使用方法
在做一个读取远程抓取数据并显示的demo的时候,遇到了以下几个问题: 1.用的curl变量进行了多定义 2.抓取远程数据时没有返回正确的json数据 没有返回正确的json数据不是因为网站提供的接口问 ...
- SPSS Modeler数据挖掘:回归分析
SPSS Modeler数据挖掘:回归分析 1 模型定义 回归分析法是最基本的数据分析方法,回归预测就是利用回归分析方法,根据一个或一组自变量的变动情况预测与其相关的某随机变量的未来值. 回归分析是研 ...
- 09_springmvc图片上传
一.上传图片 1.需求 在修改商品页面,添加上传商品图片的功能 2.springmvc中对多部件类型解析 在页面form中提交enctype="multipart/form-data&quo ...
- <day003>登录+爬取淘宝商品信息+字典用json存储
任务1:利用cookie可以免去登录的烦恼(验证码) ''' 只需要有登录后的cookie,就可以绕过验证码 登录后的cookie可以通过Selenium用第三方(微博)进行登录,不需要进行淘宝的滑动 ...
- wdatapicker 时间选择器——例
效果: html: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...
- java_网络编程之上传文件案例
初期成果: 客户端: package FileUpload; import java.io.*; import java.net.Socket; import java.util.Scanner; p ...
- C++开发系列-纯虚函数和抽象类
概念 纯虚函数和抽象类 纯虚函数是一个在基类中说明的虚函数,在基类中没有定义,要求任何派生类都实现该函数. 纯虚函数为各派生类提供了一个公共界面(接口的封装和设计.软件的模块功能的划分) 纯虚函数说明 ...