UVa 11806 拉拉队(容斥原理)

https://vjudge.net/problem/UVA-11806

题意:

在一个m行n列的矩形网格里放k个相同的石子,有多少种方法?每个格子最多放一个石子,所有石子都要用完,并且第一行、最后一行、第一列、最后一列都得有石子。

思路:

如果考虑各种情况的话很复杂,设满足第一行没有石子的方案集为A,最后一行没有石子的方案集为B,第一列没有石子的方案集为C,最后一列没有石子的方案集为D,全集为S。

一个容斥原理的公式就可以解答出来,用二进制来枚举方案集的组合。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <queue>
 6 #include <cmath>
 7 using namespace std;
 8
 9 const int mod = 1000007;
10 const int maxn = 500+5;
11
12 int c[maxn][maxn];
13
14 void init()
15 {
16     for (int i = 0; i <= maxn; i++)
17     {
18         c[i][0] = c[i][i] = 1;
19         for (int j = 1; j < i; j++)   c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
20     }
21 }
22
23 int main()
24 {
25     //freopen("D:\\input.txt", "r", stdin);
26     int T;
27     int kase = 0;
28     int n, m, k;
29     scanf("%d", &T);
30     init();
31     while (T--)
32     {
33         scanf("%d%d%d", &n, &m, &k);
34         int sum = 0;
35         for (int S = 0; S<16; S++)
36         {
37             //S=0时就相当于计算c[n*m][k],不考虑条件时的所有方法数
38             int b = 0, row = n, col = m;
39             if (S & 1)  { row--; b++; }
40             if (S & 2)  { row--; b++; }
41             if (S & 4)  { col--; b++; }
42             if (S & 8) { col--; b++; }
43             if (b & 1)   sum = (sum + mod - c[row*col][k]) % mod;
44             else sum = (sum + c[row*col][k]) % mod;
45         }
46         printf("Case %d: %d\n", ++kase, sum);
47     }
48     return 0;
49 }
时间: 2024-10-29 19:11:15

UVa 11806 拉拉队(容斥原理)的相关文章

uva 11806 - Cheerleaders(容斥原理)

题目链接:uva 11806 - Cheerleaders 题目大意:在一个m行n列的矩阵网里放k个石子,问有多少种画法?每个格子最多放一个石子,所有石子必须用完,并且在第一行.最后一行.第一列和最后一列都得有石子. 解题思路:容斥原理,我们可以先求说在m?n的矩阵上放k个石子的种数C(nmk),减掉四条边界不放的情况就是答案了.所以枚举16种状态,用二进制数表示说四条边中那些边是不放石子的. 代码 #include <cstdio> #include <cstring> cons

uva 11806 - Cheerleaders(容斥原理+二进制)

题目链接点击打开链接 题意: n行m列网格放k个石子.有多少种方法?要求第一行,第一列,最后一行,最后一列必须有石子. 思路: 1.利用容斥原理的拓展 假设有三个集合 S 另有三个集合A B C,不属于 A.B.C任何一个集合,但属于全集S的元素, 奇数个减:偶数个加 此处是S为空集  A.B.C.D分别代表 行 列中的四种情况: AUBUCUD = |A| + |B| + |C| + |D| - |AB| - |BC| - |AC| - |AD| - |BD| - |CD| + |ABC| +

UVA 11806 - Cheerleaders(数论+容斥原理)

题目链接:11806 - Cheerleaders 题意:在一个棋盘上,要求四周的四行必须有旗子,问有几种摆法. 思路:直接算很容易乱掉,利用容斥原理,可知AUBUCUD = |A| + |B| + |C| + |D| - |AB| - |BC| - |AC| - |AD| - |BD| - |CD| + |ABC| + |ABD| + |ACD| + |BCD| - |ABCD| 由此利用位运算去计算即可 代码: #include <stdio.h> #include <string.

UVA - 11806 - Cheerleaders (递推)

UVA - 11806 Cheerleaders Time Limit: 2000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description C Cheerleaders In most professional sporting events, cheerleaders play a major role in entertaining the spectators. Their roles a

UVA 1393 - Highways (容斥原理计数)

题目链接:1393 - Highways 题意:给定一个n * m的点阵,问两两相连后,能组成多少条至少穿过两个点的直线,并且不是水平或垂直的 思路:找过两点的线段,由于是整数坐标,只要他的斜率不是整数,即x / y不是整数就能满足答案,然后先记录下这所有的位置,然后利用容斥原理求出对应每个点可以连出多少条这样的线段,最后去求和,求和的时候要注意,由于有一些是重复计算了,比如1 1 和 2 2 连,2 2 和 3 3 连,这样其实是算一条的,所以最后在求和的时候要扣掉重复的部分,直接减去sum[

UVA - 11806 Cheerleaders (容斥原理)

题意:在N*M个方格中放K个点,要求第一行,第一列,最后一行,最后一列必须放,问有多少种方法. 分析: 1.集合A,B,C,D分别代表第一行,第一列,最后一行,最后一列放. 则这四行必须放=随便放C[N * M][K] - 至少有一行没放,即ABCD=随便放-A的补集 ∪ B的补集 ∪ C的补集 ∪ D的补集. 2.A的补集 ∪ B的补集 ∪ C的补集 ∪ D的补集,可用容斥原理计算,二进制枚举即可. #include<cstdio> #include<cstring> #incl

uva 11806 容斥原理+二进制

很容易想到要用容斥原理,这里有一个小技巧就是用二进制数来表示集合的交. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 typedef long long ll; 7 const int MOD = 1000007; 8 const int N = 501; 9 int cn[N][N]; 10 11 void init() 12 { 13

【递推】【组合数】【容斥原理】UVA - 11806 - Cheerleaders

http://www.cnblogs.com/khbcsu/p/4245943.html 本题如果直接枚举的话难度很大并且会无从下手.那么我们是否可以采取逆向思考的方法来解决问题呢?我们可以用总的情况把不符合要求的减掉就行了. 首先我们如果不考虑任何约束条件,我们可以得出如下结论:                                                                       下载我们假定第一行不站拉拉队员的所有的站立方法有A种.最后一行不站拉拉队员的

uva 1393 - Highways(容斥原理)

题目连接:uva 1393 - Highways 题目大意:给定一个m?n的矩阵,将矩阵上的点两两相连,问有多少条直线至少经过两点. 解题思路:头一次做这样的题目,卡了一晚上. dp[i][j]即为i?j的矩阵中有多少条红色的线,然后最后答案*2,即水平翻转下蓝色的线.非常easy发现,全部的线都过ij互质的点(即最大公约数为1).然后用容斥原理求出ans. #include <cstdio> #include <cstring> const int N = 305; int n,