博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UVA 11806 Cheerleaders (容斥原理
阅读量:5129 次
发布时间:2019-06-13

本文共 1563 字,大约阅读时间需要 5 分钟。

1.题意描述

本题大致意思是讲:给定一个广场,把它分为M行N列的正方形小框。现在给定有K个拉拉队员,每一个拉拉队员需要站在小框内进行表演。但是表演过程中有如下要求:

(1)每一个小框只能站立一个拉拉队员;

(2)广场的第一行,最后一行,第一列,最后一列都至少站有一个拉拉队员;

(3)站在广场的四个角落的拉拉队员可以认为是同时占据了一行和一列。

2.思路分析:

本题如果直接枚举的话难度很大并且会无从下手。那么我们是否可以采取逆向思考的方法来解决问题呢?我们可以用总的情况把不符合要求的减掉就行了。

首先我们如果不考虑任何约束条件,我们可以得出如下结论:

                                                                     

下载我们假定第一行不站拉拉队员的所有的站立方法有A种。最后一行不站拉拉队员的所有的方法有B种。第一列不站拉拉队员的所有的站立方法有C种。最后一列不站拉拉队员的站立方法有D种。

下面我们可以得出最后结果:

                              

下面问题来了我们如何利用代码实现容斥原理呢?我们可以借用离散数学的最大项和最小项知识结合与运算来判断每一项的特征。比如说,含A的和1进行与运算。含B的与2进行与运算。含C的和4进行与运算。含D的和8进行与运算。

然后对于每一种状态,我们利用数字0-15来代替。

在进行这些工作之前,我们还要进行基础性工作,数据初始化和 组合数公式 打表。

 

A代表包括第一行

B代表包括最后一行

C代表包括第一列

D代表包括最后一列

#include 
using namespace std;int n,m,k;const int mod = 1000007;int c[510][510];void init (){ c[0][0] = 1; for(int i=1; i <= 500;i++) { c[i][0] = c[i][i] = 1; for(int j=1;j < i;j++) { c[i][j] = (c[i-1][j-1] + c[i-1][j])%mod; } }}int main(){ init(); int t; scanf("%d",&t); for(int cas =1 ; cas <= t ;cas++) { scanf("%d %d %d",&n,&m,&k); int sum = 0; for(int i=0;i < 16;i++) { int n1= n,m1= m; int b = 0; if(i & 1) b++,n1--; if(i & 2) b++,n1--; if(i & 4) b++,m1--; if(i & 8) b++,m1--; if( b & 1 ) sum = (sum +mod - c[n1*m1][k])%mod; else sum = (sum + c[n1*m1][k])%mod; } printf("Case %d: %d\n",cas,sum); } return 0;}

 

转载于:https://www.cnblogs.com/Draymonder/p/7305749.html

你可能感兴趣的文章
利用Scrapy爬取所有知乎用户详细信息并存至MongoDB
查看>>
SQL Server 监控统计阻塞脚本信息
查看>>
分析linux进程模型
查看>>
iOS7 故事版创建tanbar
查看>>
Hibernate 的原生 SQL 查询
查看>>
PHP 环境搭建及zabbix安装遇到的一些坑.
查看>>
MYSQL常用函数(系统信息函数)
查看>>
class 模拟继承
查看>>
jquery的each()详细介绍
查看>>
简单说说装饰模式
查看>>
操作系统实验三进程调度
查看>>
冒泡排序
查看>>
板邓:php+mayql分页原理及案例
查看>>
BizTalk调用SAP系统RFC含多个参数以及DateTime类型参数
查看>>
数据分析的道与术
查看>>
2019.03.25 Ajax三级联动
查看>>
[开源]使用C# 对CPU卡基本操作封装
查看>>
NGUI3.5系列教程之 UILabel
查看>>
吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-zoom-out...
查看>>
jsp页面输出当前时间
查看>>