[CQOI2011]放棋子 题解(dp+组合数学)
Description
Input
Output
输出仅一行,即方案总数除以 1,000,000,009的余数。
Sample Input
3 1
Sample Output
$Solution$
20%:爆搜,没甚么技术含量虽然我考场上还是没打对只骗到10分Orz
100%:
考虑dp
设$f[i][j][k]$为前k种颜色的棋子占任意i行j列的方案数
那么这个值肯定是前面一系列值的$\sum$
显然需要枚举两层$0<=l<i\ ,\ 0<=r<j$
之后就可以得到$f[l][r][k-1]$并将其累加
但因为我们设的状态是任意行列
需要在剩下的$n-l$行中选$i-l$行,列的话同理
所以要$*C_{n-l}^{i-l}*C_{m-r}^{j-r}$,
而且如果要转移过去还必须乘上某一种颜色占任意i行j列的方案数
这时设$g[i][j][k]$表示k枚同色棋子占任意i行j列的方案数
可得:
$f[i][j][k] = \sum _ {l = 0} ^ {i - 1} \sum _ {r = 0} ^ {j - 1} f[l][r][k - 1] * g[i - l][j - r][a[k]] * C_{n - l} ^ {i - l} * C_{m - r} ^ {j - r}$
正向求g比较困难,我们可以逆向思维,用所有方案数-不合法方案数之和
$g[i][j][k] = C_{i j} ^ {k} - \sum _ {l = 1} ^ {i} \sum _ {r = 1} ^ {j} g[l][r][k] * C_{i}^{l} * C_{j} ^ {r}$
最后统计$ans=\sum _ {i = 1} ^ {n} \sum _ {j = 1} ^ {m} f[i][j][c]$
收获:如果觉得状态设计得当,而缺少转移方程的某一部分时,不妨设一个辅助数组单独考虑。
#include<cstdio> #include<iostream> using namespace std; typedef long long ll; int n,m,c,a[35]; const ll mod=1e9+9; ll f[35][35][15],g[35][35][920],ans=0,C[920][920]; int main() {scanf("%d%d%d",&n,&m,&c);for(int i=1;i<=c;i++)scanf("%d",&a[i]);if(c>min(n,m)){puts("0");return 0;}f[0][0][0]=1;C[0][0]=1;for(int i=1;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;}for(int k=1;k<=c;k++)for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(a[k]>i*j)continue;ll res=0;g[i][j][a[k]]=C[i*j][a[k]];for(int l=1;l<=i;l++)for(int r=1;r<=j;r++)if(l<i||r<j)(res+=C[i][l]*C[j][r]%mod*g[l][r][a[k]]%mod)%=mod; g[i][j][a[k]]=(g[i][j][a[k]]-res+mod)%mod;}for(int k=1;k<=c;k++)for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)for(int l=0;l<i;l++)for(int r=0;r<j;r++) (f[i][j][k]+=C[n-l][i-l]*C[m-r][j-r]%mod*f[l][r][k-1]%mod*g[i-l][j-r][a[k]]%mod)%=mod;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)(ans+=f[i][j][c])%=mod;cout<<ans<<endl;return 0; }
转载于:https://www.cnblogs.com/Rorschach-XR/p/11156452.html
[CQOI2011]放棋子 题解(dp+组合数学)相关推荐
- 【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
3294: [Cqoi2011]放棋子 Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数 ...
- [CQOI2011]放棋子
C. 放棋子 题目描述 输入格式 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数. 第二行包含c个正整数,即每个颜色的棋子数. 所有颜色的棋子总数保证不超过nm. N,M<=30 ...
- BZOJ3294 CQOI2011放棋子(动态规划)
可以看做棋子放在某个位置后该种颜色就占领了那一行一列.行列间彼此没有区别. 于是可以设f[i][j][k]表示前k种棋子占领了i行j列的方案数.转移时枚举第k种棋子占领几行几列.注意行列间是有序的,要 ...
- 数论三之组合数学Ⅰ-Max-Min Sums,Binomial Coefficient is Fun,Strivore,Bubble Sort,放棋子,LOJ6671,Iroha and a Grid
组合计数我最爱 Max-Min Sums description solution code Binomial Coefficient is Fun description solution code ...
- BZOJ4563[Haoi2016]放棋子
题目描述 Description 给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在 这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子 ...
- [BZOJ 4563]放棋子
[BZOJ 4563]放棋子 题目 给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子 ...
- CodeForces - 336D Vasily the Bear and Beautiful Strings(dp+组合数学)
题目链接:点击查看 题目大意:给出一个 01 字符串,规定求值的过程如下: 每次选择末尾的两个数字: 如果为 0 0 ,那么替换成一个 1 否则替换成一个 0 循环往复,直至只剩一个数字位置,剩下的数 ...
- 洛谷 P3182 [HAOI2016]放棋子(错排问题)
题面 luogu 题解 裸的错排问题 错排问题 百度百科:\(n\)个有序的元素应有\(n!\)个不同的排列,如若一个排列使得所有的元素不在原来的位置上,则称这个排列为错排:有的叫重排.如,1 2的错 ...
- UVA11134传说中的车(放棋子)
题意: 给你一个n*n的棋盘,让你在棋盘上放n个棋子,要求是所有棋子不能相互攻击(同行或者同列就会攻击),并且每个棋子都有一个限制,那就是必须在给定的矩形r[i]里,输出每个棋子的位置,s ...
最新文章
- 端到端TVM编译器(下)
- vmware esxi的安装
- 玩转springboot:日志的使用
- C#中枚举类型的声明与使用举例
- COS系统的前端演变和发展
- 面试精讲之面试考点及大厂真题 - 分布式专栏 02 了解大厂面试基本套路及每一轮的重点
- 请查收,一份让你年薪突破20W的Python爬虫笔记!
- 使用回收站主键名、索引名问题
- php跨域问题,PHP跨域问题解决方案
- 用python计算邮费考虑是否加急,用python计算residuals
- XPC connection interrupted
- mysql的cpu使用率突然增高_mysql cpu使用率过高解决方法
- GetImageBuffer
- 国内三大云平台,IoT物联网实例选购指南
- 土地利用覆被变化的概念_土地利用/覆被变化(LUCC)研究现状与展望
- CHB-MIT波士顿儿童医院癫痫EEG脑电数据处理-癫痫发作预测(六)
- h264—CABAC算法原理简介1
- Linux服务器封IP,linux 封IP iptables
- SpringBoot访问windows共享文件
- 维克仓库管理软件 v3.4 绿色
热门文章
- JAVA编程规则【转自java编程思想】
- 红帽linux lnmp搭建,RedHat/CentOs系统搭建lnmp环境
- Android四大组件---BroadcastReceiver
- 新年新计划-2021年
- “命令终端”的实现3-命令的执行
- 以太网的phy寄存器分析
- 我的内核学习笔记4:sysfs学习
- 一台电脑连接到另外一台电脑的虚拟机里面的系统
- 在拦截器里放入参数 controller_干货|SpringMVC拦截器的使用详解
- 【Flink】Flink exactly-once 报错 Timeout expired after 60000 milliseconds while awaiting InitProducerId