题意:在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同颜色的棋子不能在同一行或者同一列。有多少祌方法?

解法:这道题不会做,太菜了qwq。题解是看洛谷大佬的。

设C是组合数,f[i][j][k]:代表前k种棋子合法地恰好占领i行j列

那么得到状态转移方程:f[i][j][k]=sigma f[ki][kj][k-1] * C[n-ki][i-ki] * C[m-kj][j-kj] * a[k]个棋子恰好占领i-ki行j-kj列的方案数。 这个式子的意思是我们枚举前k-1种棋子的占领情况是行占领ki行列占领kj列,那么第k种棋子就能占领i-ki行j-kj列,我们选出这i-ki/j-kj之后乘上通知颜色棋子a[k]个占领这i-ki/j-kj的方案数。

我们发现前面都都比较好算,唯独 a[k]个棋子恰好占领i-ki行j-kj列的方案数 这一项难算。

那么我们就考虑单独先预处理出这一项,设g[i][j][k]:代表k个同色棋子恰好占领了i行j列 ;

那么写出状态转移方程:g[i][j][k]=C[i*j][k] - sigma g[ki][kj][k] * C[i][i-ki] * C[j][j-kj] ;式子的意思是总的方案数减去不合法方案数,即同样是k个棋子却没有占满i行j列。

那么我们预处理出C数组和g数组,就可以获得AC了。

 #include<bits/stdc++.h>
using namespace std;
const int N=+;
const int P=1e9+;
typedef long long LL;
int n,m,c,a[N];
int C[N*][N*],f[N][N][N*],g[N][N][N*];
//g[i][j][k]:代表k个同色棋子恰好占领了i行j列
//f[i][j][k]:代表前k种棋子合法地恰好占领i行j列 void prework() {
for (int i=;i<=;i++)
for (int j=;j<=;j++)
if (j== || i==j) C[i][j]=;
else C[i][j]=(C[i-][j-]+C[i-][j])%P;
} int main()
{
cin>>n>>m>>c;
int sum=;
for (int i=;i<=c;i++) scanf("%d",&a[i]),sum+=a[i];
prework(); for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
for (int k=;k<=sum;k++) {
if (i*j<k) continue;
g[i][j][k]=C[i*j][k];
for (int ki=;ki<=i;ki++)
for (int kj=;kj<=j;kj++)
if (ki!=i || kj!=j) g[i][j][k]=(g[i][j][k]-(LL)g[ki][kj][k]*C[i][ki]%P*C[j][kj]%P)%P;
g[i][j][k]=(g[i][j][k]%P+P)%P;
} LL ans=;
f[][][]=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
for (int k=;k<=c;k++) {
for (int ki=;ki<=i;ki++)
for (int kj=;kj<=j;kj++)
if ((i-ki)*(j-kj)>=a[k])
f[i][j][k]=(f[i][j][k]+(LL)f[ki][kj][k-]*C[n-ki][i-ki]%P*C[m-kj][j-kj]%P*g[i-ki][j-kj][a[k]]%P)%P;
if (k==c) ans=(ans+f[i][j][k])%P;
}
cout<<ans<<endl;
return ;
}

洛谷P3158 [CQOI2011]放棋子 组合数学+DP的更多相关文章

  1. [洛谷P3158] [CQOI2011]放棋子

    洛谷题目链接:[CQOI2011]放棋子 题目描述 在一个m行n列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同 颜色的棋子不能在同一行或者同一列.有多少祌方法?例如,n=m=3,有两个 ...

  2. P3158 [CQOI2011]放棋子(dp+组合数)

    P3158 [CQOI2011]放棋子 放棋子的顺序和方案数无关,所以可以从按颜色递推 设$f[u][p][k]$为放到第$u$种颜色,所剩空间$p*k$的方案数 $g[u][i][j]$表示第$u$ ...

  3. 【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)

    3294: [Cqoi2011]放棋子 Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数 ...

  4. [CQOI2011]放棋子 (DP,数论)

    [CQOI2011]放棋子 \(solution:\) 看到这道题我们首先就应该想到有可能是DP和数论,因为题目已经很有特性了(首先题面是放棋子)(然后这一题方案数很多要取模)(而且这一题的数据范围很 ...

  5. 洛谷 P3182 [HAOI2016]放棋子(高精度,错排问题)

    传送门 解题思路 不会错排问题的请移步——错排问题 && 洛谷 P1595 信封问题 这一道题其实就是求对于每一行的每一个棋子都放在没有障碍的地方的方案数. 因为障碍是每行.每列只有一 ...

  6. 洛谷P3182 [HAOI2016]放棋子

    P3182 [HAOI2016]放棋子 题目描述 给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要 ...

  7. [CQOI2011]放棋子 题解(dp+组合数学)

    Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数. 第二行包含c个正整数,即每个颜色的棋子数. 所有颜色的棋子总数保证不超过nm. N,M<=3 ...

  8. 题解 P3158 [CQOI2011]放棋子

    题解 本题是一个 \(DP\) 加 容斥,容斥的式子很好推,重点是如何想到和如何推出 \(DP\) 部分的式子. 因为不同种颜色的棋子不能放在同一行或同一列,所以不同种的棋子是相对独立的. 据此,我们 ...

  9. 洛谷 P3182 [HAOI2016]放棋子(错排问题)

    题面 luogu 题解 裸的错排问题 错排问题 百度百科:\(n\)个有序的元素应有\(n!\)个不同的排列,如若一个排列使得所有的元素不在原来的位置上,则称这个排列为错排:有的叫重排.如,1 2的错 ...

随机推荐

  1. SpringBoot:使用IDEA快速构建项目

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处!防君子不防小人,共勉! SpringBoot ...

  2. SpringBoot:初识SpringBoot

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处!防君子不防小人,共勉! 1.SpringBo ...

  3. C3P0 详解

    定义: C3P0是一个开源的JDBC连接池,目前使用它的开源项目有Hibernate,Spring等. 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”.预先在缓冲池中放入一定数量的连接,当需 ...

  4. Linux内核调试方法总结之dumpsys

    dumpsys [用途]Android系统提供的dumpsys工具可以用来查看系统服务信息与状态. [使用说明] adb shell dumpsys <service> [<opti ...

  5. nginx下使用asan和valgrind两个静态检查工具

    1.valgrind valgrind安装:参考:https://blog.csdn.net/justheretobe/article/details/52986461 wegit:http://va ...

  6. Java面试中hashCode()与equals(Object obj)方法关系的准确回答

    原文地址: https://blog.csdn.net/qq_19260029/article/details/77917925 hashCode()与equals(Object obj)都是Java ...

  7. Vue中解决路由切换,页面不更新的实用方法

    前言:vue-router的切换不同于传统的页面的切换.路由之间的切换,其实就是组件之间的切换,不是真正的页面切换.这也会导致一个问题,就是引用相同组件的时候,会导致该组件无法更新,也就是我们口中的页 ...

  8. Linux pip命令报错 -bash: pip: command not found

    下载 $ wget https://bootstrap.pypa.io/get-pip.py 安装 $ python get-pip.py 查看版本 $ pip -V 查看安装路径: find / - ...

  9. C#怎么让字符串定长,不够的用空格补齐

    string.PadLeft 或者 string.PadRight  : string.PadLeft 表示如果一个字符串的长度小于指定的值,则在字符串的左侧(也就是前面)用指定的字符填充,直到字符串 ...

  10. sqoop应用

    1.导入数据(将mysql(rdbms)的表的数据导入到hdfs) 1.1.全部导入(注意空格) sqoop import \ --connect jdbc:mysql://192.168.159.1 ...