BZOJ3294: [Cqoi2011]放棋子(计数Dp,组合数学)
解题思路:
发现一个性质,如果考虑一个合法的方案可以将行和列都压到一起,也就是说,在占用行数和列数一定的情况下,行列互换是不会影响答案的,那么考虑使用如下方程:
$f[i][j][k]$为占领了i行j列使用了前k种颜色,由于要求全部用完,不需要枚举放入多少,考虑一个一个来添加颜色。考虑添加第k种颜色:
因为第k种颜色一定是占据了新的一行一列,所以加入第k种颜色后的行数=加入之前的行数+第k种颜色占据的行数,列数同理。
设第k种颜色的棋子有a个,那么我们只需要知道用A种颜色占据i行j列的方案数,设为$g[i][j][A]$这个可以使用容斥
转移即为$g[i][j][A]=C_{i*j}^A-\limits\sum_{a=1}^{i}\limits\sum_{b=1}^{j}g[a][b][A]*C_i^a*C_j^b$发现和A毛关系没有就舍去了这一维。
所以最后的转移就是:
$f[i][j][k]=\limits\sum_{a=1}^{i}\limits\sum_{b=1}^{j}f[i-a][i-b][k-1]*g[a][b]*C_{n-i+a}^{a}*C_{m-j+b}^{b}$
答案就是i,j的累和。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
const lnt mod=(lnt)(1e9+);
lnt f[][][];
lnt g[][];
int num[];
lnt C[][];
int n,m,c;
void get_g(int k)
{
memset(g,,sizeof(g));
int A=num[k];
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(i*j>=A)
{
g[i][j]=C[i*j][A];
for(int a=;a<=i;a++)
{
for(int b=;b<=j;b++)
{
if(a==i&&b==j)continue;
(g[i][j]-=g[a][b]*C[i][a]%mod*C[j][b]%mod)%=mod;
}
}
}
}
}
return ;
}
void init(void)
{
C[][]=;
for(int i=;i<=;i++)
{
C[i][]=;
for(int j=;j<=i;j++)
{
C[i][j]=(C[i-][j-]+C[i-][j])%mod;
}
}
return ;
}
int main()
{
scanf("%d%d%d",&n,&m,&c);
for(int i=;i<=c;i++)scanf("%d",&num[i]);
init();
f[][][]=;
for(int k=;k<=c;k++)
{
get_g(k);
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(i*j<num[k])continue;
for(int a=i;a<=n;a++)
{
for(int b=j;b<=m;b++)
{
(f[a][b][k]+=f[a-i][b-j][k-]*g[i][j]%mod*C[n-a+i][i]%mod*C[m-b+j][j]%mod)%=mod;
}
}
}
}
}
lnt ans();
for(int i=;i<=n;i++)for(int j=;j<=m;j++)(ans+=f[i][j][c])%=mod;
printf("%lld\n",(ans%mod+mod)%mod);
return ;
}
BZOJ3294: [Cqoi2011]放棋子(计数Dp,组合数学)的更多相关文章
- 【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
3294: [Cqoi2011]放棋子 Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数 ...
- [CQOI2011]放棋子 题解(dp+组合数学)
Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数. 第二行包含c个正整数,即每个颜色的棋子数. 所有颜色的棋子总数保证不超过nm. N,M<=3 ...
- BZOJ 3294: [Cqoi2011]放棋子(计数dp)
传送门 解题思路 设\(f[i][j][k]\)表示前\(k\)个颜色的棋子占领了\(i\)行\(j\)列的方案数,那么转移时可以枚举上一个颜色时占领的位置,\(f[i][j][k]=\sum\lim ...
- bzoj3294[Cqoi2011]放棋子 dp+组合+容斥
3294: [Cqoi2011]放棋子 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 755 Solved: 294[Submit][Status] ...
- [CQOI2011]放棋子 (DP,数论)
[CQOI2011]放棋子 \(solution:\) 看到这道题我们首先就应该想到有可能是DP和数论,因为题目已经很有特性了(首先题面是放棋子)(然后这一题方案数很多要取模)(而且这一题的数据范围很 ...
- bzoj千题计划261:bzoj3294: [Cqoi2011]放棋子
http://www.lydsy.com/JudgeOnline/problem.php?id=3294 如果一个颜色的棋子放在了第i行第j列,那这种颜色就会占据第i行第j列,其他颜色不能往这儿放 设 ...
- P3158 [CQOI2011]放棋子(dp+组合数)
P3158 [CQOI2011]放棋子 放棋子的顺序和方案数无关,所以可以从按颜色递推 设$f[u][p][k]$为放到第$u$种颜色,所剩空间$p*k$的方案数 $g[u][i][j]$表示第$u$ ...
- BZOJ3294: [Cqoi2011]放棋子
Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数保证不超过nm. Output 输出 ...
- BZOJ 3294: [Cqoi2011]放棋子 计数 + 容斥 + 组合
比较头疼的计数题. 我们发现,放置一个棋子会使得该棋子所在的1个行和1个列都只能放同种棋子. 定义状态 $f_{i,j,k}$ 表示目前已使用了 $i$ 个行,$j$ 个列,并放置了前 $k$ 种棋子 ...
随机推荐
- angularjs 表单校验
<!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...
- hpuoj--校赛--2015年的第一场雪(暴力)
问题 D: 感恩节KK专场--2015年的第一场雪 时间限制: 1 Sec 内存限制: 128 MB 提交: 865 解决: 76 [提交][状态][讨论版] 题目描述 下雪了,KK学长站在三教门 ...
- Linux中的find命令
.递归查找(find 命令 是递归遍历文件夹的) 命令:find . -name “*.txt” //当前路径下递归查找以.txt结尾的文件夹 .不递归查找 find . -name “*.txt” ...
- 如何让alertdialog选择完后自动关闭
builder.setIcon(R.drawable.ic_system) .setTitle("串口号") .setSingleChoiceItems(mPorts, mSele ...
- P1452 Beauty Contes
题目背景 此处省略1W字^ ^ 题目描述 贝茜在牛的选美比赛中赢得了冠军”牛世界小姐”.因此,贝西会参观N(2 < = N < = 50000)个农场来传播善意.世界将被表示成一个二维平面 ...
- 在Ubuntu下使用命令删除目录
在Ubuntu命令行中用命令删除目录,现在在Linux系统中删除目录大致会用两个,rm和rmdir,rm命令删除目录很简单,不过很多人还是比较习惯用rmdir命令,如果操作的目录非空时就有点麻烦.这时 ...
- AngularJs轻松入门(九)与服务器交互
AngularJs从Web服务器请求资源都是通过Ajax来完成,所有的操作封装在$http服务中,$http服务是只能接收一个参数的函数,这个参数是一个对象,用来完成HTTP请求的一些配置,函数返回一 ...
- RelativeLayout中的baseline
比如,加入两个相邻的TextView,给第二个TextView一个大一点的padding(比如20dp),如果加了layout_alignBaseline到第二个TextView中的话, TextVi ...
- AngularJS 导航栏动态添加.active
在传统jQuery中,实现导航栏动态添加.active类的思路比较简单,就是当点击的时候,清除其他.active,然后给当前类加上.active. 但是在AngularJS中,就不能再采用这种jQue ...
- WLAN RTT (IEEE 802.11mc)
WLAN RTT (IEEE 802.11mc) Android 9 中的 WLAN 往返时间 (RTT) 功能允许设备测量与其他支持设备的距离:无论它们是接入点 (AP) 还是 WLAN 感知对等设 ...