例题2.3 拉拉队 UVa11806

1.题目描述:点击打开链接

2.解题思路:本题利用容斥原理解决。首先我们解决一个简单的问题:如何求解“第一行,最后一行,第一列,最后一列都没有石子”的方案数。这相当于只有m-2行和n-2列,答案为C((m-2)(n-2),k)。那么如果我们可以想办法把本题分解为一系列这个简单问题的线性组合,即可求解出答案。这正是容斥原理的作用。

设满足“第一行没有石子”的方案集为A,最后一行没有石子的方案集为B,第一列没有石子的方案集为C,最后一列没有石子的方案集为D,全集为S。那么问题的答案就是“在S中但不在A,B,C,D任何一个子集中”的元素个数。这正好就是容斥原理的经典问题。

在程序中,我们用二进制表示A,B,C,D的所有“搭配”。如果在集合A或集合B中,就相当于少了一行;如果在集合C或集合D中,就相当于少了一列。假设最后只剩下了r行c列,那么方案数就是C(rc,k)。而这样的搭配一共只有16种情况。

注意:在应用容斥原理时,不要试图一步到位写出完整的公式,而应该逐个逐个地依次计算,只要有奇数个条件,就做减法, 偶数个条件就做加法。这就是容斥原理的基本运算方法。

3.代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
typedef pair<long long, long long> PL;
#define me(s) memset(s,0,sizeof(s))
#define For(i,n) for(int i=0;i<(n);i++)

const int MOD = 1000007;
const int K = 500 + 10;
int C[K][K];

void init()
{
	me(C);
	C[0][0] = 1;
	for (int i = 0; i < K; i++)
	{
		C[i][0] = C[i][i] = 1;
		for (int j = 1; j < i; j++)
			C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
	}
}

int main()
{
	//freopen("t.txt", "r", stdin);
	init();
	int T;
	scanf("%d", &T);
	int rnd = 0;
	while (T--)
	{
		int n, m, k, sum = 0;
		scanf("%d%d%d", &n, &m, &k);
		for (int S = 0; S < 16; S++)//一共16种搭配
		{
			int b = 0, r = n, c = m;//b统计搭配的个数,r,c是可放置的行数和列数
			if (S & 1){ r--; b++; }
			if (S & 2){ r--; b++; }
			if (S & 4){ c--; b++; }
			if (S & 8){ c--; b++; }
			if (b & 1)sum = (sum + MOD - C[r*c][k]) % MOD;//奇数个搭配,做减法
			else sum = (sum + C[r*c][k]) % MOD;//偶数个搭配,做加法
		}
		printf("Case %d: %d\n", ++rnd, sum);
	}
	return 0;
}
时间: 2024-08-26 10:35:31

例题2.3 拉拉队 UVa11806的相关文章

UVA11806【拉拉队】Cheerleaders-------2015年1月24日

1.题意描述 本题大致意思是讲:给定一个广场,把它分为M行N列的正方形小框.现在给定有K个拉拉队员,每一个拉拉队员需要站在小框内进行表演.但是表演过程中有如下要求: (1)每一个小框只能站立一个拉拉队员: (2)广场的第一行,最后一行,第一列,最后一列都至少站有一个拉拉队员: (3)站在广场的四个角落的拉拉队员可以认为是同时占据了一行和一列. 2.思路分析: 本题如果直接枚举的话难度很大并且会无从下手.那么我们是否可以采取逆向思考的方法来解决问题呢?我们可以用总的情况把不符合要求的减掉就行了.

acm常见算法及例题

转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法:     (1)枚举. (poj1753,poj2965)     (2)贪心(poj1328,poj2109,poj2586)     (3)递归和分治法.     (4)递推.     (5)构造法.(poj3295)     (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法

黑书例题 Fight Club 区间DP

题目可以在bnuoj.soj等OJ上找到. 题意: 不超过40个人站成一圈,只能和两边的人对战.给出任意两人对战的输赢,对于每一个人,输出是否可能是最后的胜者. 分析: 首先序列扩展成2倍,破环成链. dp[i][j]表示i和j能够相遇对打,那么dp[i][i+n]为真代表可以成为最后胜者. 枚举中间的k,若i和j都能和k相遇,且i和j至少一人能打赢k,那么i和j可以相遇. 复杂度o(n^3) 1 #include<cstdio> 2 #include<cstring> 3 usi

linux脚本进阶例题解析

例题一:编写脚本/root/bin/createuser.sh,实现如下功能: 使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之:并生成8位随机口令并存在一个文件中,初步提示改口令,显示添加的用户的id号等信息 #!/bin/bash # ------------------------------------------ # Filename: useradd.sh  # Revision: null # Date: 2017-09-11 21:47:22 # Auth

bzoj 2160: 拉拉队排练

Description 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要.拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材.舞技于一体的美女从众多报名的女生中脱颖而出.这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威.一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练.n个女生从左到右排成一行,每个人手中都

JAVA基础汇总及例题详解

java语言的一个核心: jdk, java development kits---面向开发人员 jre, java Runtime Environment---服务器上 java虚拟机---(以字节码为指令的CPU)---*.class java编译器-->字节码-->类加载器进行验证-->虚拟机运行 垃圾回收机制 public class ...{ int a = 1; } c/c++垃圾回收由程序员去运行 java编程语言(一门纯面向对象)的特点: 1, 面向对象  封装  继承

【强连通分量】tarjan算法及kosaraju算法+例题

阅读前请确保自己知道强连通分量是什么,本文不做赘述. Tarjan算法 一.算法简介 Tarjan算法是一种由Robert Tarjan提出的求有向图强连通分量的时间复杂度为O(n)的算法. 首先我们要知道两个概念:时间戳(DFN),节点能追溯到的最早的栈中节点的时间戳(LOW).顾名思义,DFN就是在搜索中某一节点被遍历到的次序号(dfs_num),LOW就是某一节点在栈中能追溯到的最早的父亲节点的搜索次序号. Tarjan算法是基于深度优先搜索的算法.在搜索过程中把没有Tarjan过的点入栈

第10章例题(紫书)

21/21 题目都很基础,有很多题书上讲得比较详细,然后隔得时间有点久,所以具体什么trick都忘了,思路也懒得去回忆,所以将就着放上来了.... 例题10–1 Uva 11582 题意:输入a, b, n让你计算F[a^b]%n;其中这个F[i]是斐波那契数: 题解: 这题是快速幂+找循环节,用什么方法找循环节呢?因为第一个数是0和1,然后当再出现0和1的时候就是出现循环节的时候,然后假如找到了循环节T,然后就有F[n] = F[n % T],预处理找循环节,O(一百万左右),快速幂logn

数组模拟单向链表例题(UVa11988)

指针的链表实现方式是,当前节点的next指向下一个节点,用数组模拟就是 for(int i=next[0];i!=0;i=next[i]) i=next[i]:就是一条链. 例题: 你有一个破损的键盘.键盘上的所有键都可以正常工作,但有时Home键或者End键会自动按下.你并不知道键盘存在这一问题,而是专心打稿子,甚至连显示器都没打开.当你打开显示器时之后,展现在你面前的是一段悲剧文本.你的任务时在打开显示器之前计算出这段悲剧文本. 输入包含多组数据.每组数据占一行,包含不超过100000个字母