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$ 种棋子 ...
随机推荐
- [Perl系列—] 2. Perl 中的引用使用方法
Perl 中的引用,为什么要使用引用? 对于熟悉C语言的开发人员来说, 指针这个概念一定不陌生. Perl 的引用就是指针,能够指向变量.数组.哈希表甚至子程序. Perl5中的两种Perl引用类型为 ...
- ES聚合底层机制-bucket深的话采用广度优先更好,而如果是年度统计还是深度优先好
见原文,仅仅摘录部分:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_preventing_combinatorial_exp ...
- C++字节对齐与结构体大小计算
转载注明出处:http://pppboy.blog.163.com/blog/static/30203796201082494026399/ 感谢原创博主的辛勤成果. 说明: 结构体的sizeof值, ...
- DC、CDC及CDC的各个子类
设备描述表是一个包含设备信息的结构体(物理设备如显示器.打印机),MFC中关于图像操作都需要DC来完成.HDC是Windows的一种数据类型,是设备描述句柄:CDC是MFC封装的Windows 设 ...
- iOS单例创建的一点疑惑
线程安全的单例常用写法, +(AccountManager *)sharedManager{ static AccountManager *defaultManager = nil; disptch_ ...
- js数组的操作 Full
js数组的操作 用 js有很久了,但都没有深究过js的数组形式.偶尔用用也就是简单的string.split(char).这段时间做的一个项目,用到数组的地方很多,自以为js高手的自己居然无从下手,一 ...
- <Sicily>Pair
一.题目描述 The N cities of Estiah are connected by N-1 roads. The roads are built in a way that it's alw ...
- git新克隆代码的时候ssh协议
- JS触发按钮事件
前台代码: <asp:Button ID="btnSaveBattery" runat="server" Text="保存" OnCl ...
- Win10 +VS2015 配置openCV3.4.0
配置过程参考链接:https://www.cnblogs.com/linshuhe/p/5764394.html 其他链接:https://blog.csdn.net/weixin_39393712/ ...