3.奶牛的新家

【问题描述】

由于奶牛们纷纷表示破旧的房子实在是太丑陋了,DD决定给他们建造新家。现在有许多奶牛决定将家建造在n*m的城市中。然而奶牛们分成了k帮派,不同帮派的奶牛不能住在同列或同行上。现在DD想知道一共有多少建造方案。

【输入】

第一行三个整数n,m,k

接下来一行k个整数,分别表示每个帮派有多少只牛

【输出】

一行一个整数,建造方案数mod 100000007

【样例输入】

2 3 2

1 1

【样例输出】

12

【输入输出样例说明】

两头不同帮派的牛放在2*3的图中的方案数为12

【数据范围】

对于30%的数据,n,m≤4

对于80%的数据,n,m≤20

对于100%的数据,n,m≤30;k≤10

这是我们第二次六校联测(标题是“多校联测3”),又挂了,唉,又是死在了dp上了,烦透了。

先观察这一题,一种颜色一定是占据了若干行和若干列的,在这些行与列上是不能放别的颜色的。令g(i, j, k)表示第k种颜色恰好占据了i行j列的方案数,这里“恰好”是指这i行j列中没有哪一行或者哪一列是空的。那么有:

g(i, j, k) = C(i * j, a[k]) - sigma (   g(i', j', k) * C(i, i') * C(j, j')   ),其中要满足i' < i或 j' < j,i * j要 >= a[k](a[k]表示第k种颜色的个数),C表示的是组合。

上面那条方程的意思就是,首先要加上C(i * j, a[k])表示在这i * j个格子里放a[k]个,那么有C(i * j, a[k])种方案。减掉的那一部分的意义是:某些方案并不满足这种状态(注意状态表示的是“恰好占据”),所以需要减掉这些状态。

然后f(i, j, k)表示前k种颜色,恰好占据了i行j列的方案数,那么有:

f(i, j, k) = sigma(   f(i - i', j - j', k - 1) * g(i', j') * C(i, i') * C(j, j')   )

#include <cstdio>

const long long mod = 100000007;

int n, m, K, a[15];
long long c[1005][1005], f[35][35][15], g[35][35][15], ans; int main(void) {
scanf("%d%d%d", &n, &m, &K);
for (int i = 1; i <= K; ++i) {
scanf("%d", a + i);
}
c[0][0] = 1;
for (int i = 1; i < 1001; ++i) {
c[i][0] = 1;
for (int j = 1; j <= i; ++j) {
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
}
} for (int k = 1; k <= K; ++k) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (i * j < a[k]) {
continue;
}
g[i][j][k] = c[i * j][a[k]];
for (int i_ = 1; i_ <= i; ++i_) {
for (int j_ = 1; j_ <= j; ++j_) {
if (i_ < i || j_ < j) {
g[i][j][k] = (g[i][j][k] - (g[i_][j_][k] * c[i][i_] % mod * c[j][j_] % mod) + mod) % mod;
}
}
}
}
}
} f[0][0][0] = 1;
for (int k = 1; k <= K; ++k) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (i * j < a[k]) {
continue;
}
for (int i_ = 1; i_ <= i; ++i_) {
for (int j_ = 1; j_ <= j; ++j_) {
f[i][j][k] = (f[i][j][k] + f[i - i_][j - j_][k - 1] * g[i_][j_][k] % mod * c[i][i_] % mod * c[j][j_]) % mod;
}
}
}
}
} for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
ans = (ans + f[i][j][K] * c[n][i] % mod * c[m][j] % mod) % mod;
}
}
printf("%d\n", (int)ans);
return 0;
}

  

[ZPG TEST 111] 奶牛的新家【DP】的更多相关文章

  1. 【BZOJ-3631】松鼠的新家 树形DP?+ 倍增LCA + 打标记

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1231  Solved: 620[Submit][Stat ...

  2. 3631. [JLOI2014]松鼠的新家【树形DP】

    Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...

  3. 刷题总结——松鼠的新家(bzoj3631)

    题目: Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上. ...

  4. 此博客主人已搬家访问新家地址:http://write.blog.csdn.net/postlist

    此博客主人已搬家访问新家地址:http://write.blog.csdn.net/postlist

  5. BZOJ 3631 【JLOI2014】 松鼠的新家

    Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树&q ...

  6. 【bzoj3631】[JLOI2014]松鼠的新家

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上.松 ...

  7. 【BZOJ3631】松树的新家 树链剖分

    BZOJ3631 松树的新家 Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  8. BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )

    裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...

  9. 3631: [JLOI2014]松鼠的新家

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 707  Solved: 342[Submit][Statu ...

随机推荐

  1. MySQL 资源大全

    干货!MySQL 资源大全 提交 我的留言 加载中 已留言 shlomi-noach 发起维护的 MySQL 资源列表,内容覆盖:分析工具.备份.性能测试.配置.部署.GUI 等. 伯乐在线已在 Gi ...

  2. js:简单的拖动效果

    效果演示:https://jsfiddle.net/dwqs/b5ywws9f/embedded/result/ html: <div class="wrap"> &l ...

  3. 基于编程人员Python学习第一章节

    基于廖雪峰的python零基础学习后,自我总结.适用于有一定基础的编程人员,对我而言,则是基于.net已有方面,通过学习,记录自我觉得有用的地方,便于后续回顾. 主要以快速定位内容,通过直观代码输入输 ...

  4. React通过Ajax获取数据

    React 组件的数据可以通过 componentDidMount 方法中的 Ajax 来获取,当从服务端获取数据库可以将数据存储在 state 中,再用 this.setState 方法重新渲染 U ...

  5. 使用HD/IDE层的ioctl接口获取磁盘容量get_hdd_max_sector

    利用HD/IDE layer的ioctl函数接口获取HD/IDE的磁盘容量.HDIO_DRIVE_TASK  能发出訪问LBA地址的命令.但不能读写数据. #include <stdio.h&g ...

  6. ubuntu中查看已安装软件包的方法

    ubuntu中查看已安装软件包的方法: 方法一:在新立得软件包管理器中,打到已安装,便可以看看有多少包被安装. 如果想把这些包的信息复制到一文件里,可用下面的方法. 方法二:在终端输入 sudo dp ...

  7. ABAP doi 导出程序

    PERFORM FRM_OUTPUT_EXCEL_38 TABLES GT_RESULT USING 'ZHRPA038' LDF_PATH . FORM FRM_OUTPUT_EXCEL_38 TA ...

  8. 利用JS 阻止表单提交

    情景一:不存在Ajax异步操作 1 使用背景:会议室预定管理系统中,当表单提交的时候需要验证预约的时间是否符合预定规则(不需要通过访问服务器),否则提示错误信息,阻止表单提交. 2 相关技术点: fo ...

  9. HDU2444 The Accomodation of Students —— 二分图最大匹配

    题目链接:https://vjudge.net/problem/HDU-2444 The Accomodation of Students Time Limit: 5000/1000 MS (Java ...

  10. 7-39 Math对象

    7-39 Math对象 学习要点 掌握常用的数学计算方法 温馨提示:关于学习方法的建议 不要强求自己讲参考手册上所以的属性和方法都搞清楚,原因如下: 有些属性和方法非常生僻,很少用,甚至经过一段时间后 ...