uva11806(容斥原理)拉拉队
2017-07-20 16:31
155 查看
例题3 拉拉队(Cheerleaders, UVa 11806)
在一个m行n列的矩形网格里放k个相同的石子, 问有多少种方法? 每
个格子最多放一个石子, 所有石子都要用完, 并且第一行、 最后一行、
第一列、 最后一列都得有石子。
【输入格式】
输入第一行为数据组数T(T≤50) , 每组数据包含3个整数m,
n,
k(2≤m,
n≤20, k≤500) 。
【输出格式】
对于每组数据, 输出方案总数除以1000007的余数。
【分析】
如果题目求的是“第一行、 最后一行、 第一列、 最后一列都没有石
子”的方案数, 该有多好啊! 这相当于一共只有m-2行n-2列,
答案自然
是C((m-2) (n-2)
, k) 了。 幸运的是, 利用容斥原理, 我们可以
把本题转化为上述问题。
设满足“第一行没有石子”的方案集为A, 最后一行没有石子的方案集
为B, 第一列没有石子的方案集为C, 最后一列没有石子的方案集为D,
全集为S, 则所求答案就是“在S中但不在A,
B, C,
D任何一个集合中”的
元素个数, 可以用容斥原理求解。
在程序中, 我们用二进制来表示A,
B, C,
D的所有“搭配”(S对应
172
于“空搭配”) 。 如果在集合A和B中,
相当于少了一行; 如果在集合C或D
中, 相当于少了一列。 假定最后剩了r行c列, 方法数就是C(rc,
k) 。
#include<cstdio>
#include<iostream>
using namespace std;
const int mk=505,MOD=1000007;
int C[mk][mk];
int main()
{
//预处理出组合数
C[0][0]=1;
for(int i=1;i<mk;++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;
}
int T;
scanf("%d",&T);
for(int kase=1;kase<=T;++kase)
{
int n,m,k,sum=0;
scanf("%d%d%d",&n,&m,&k);
for(int S=0;S<16;++S)
{
int b=0,r=n,c=m;
if(S&1) r--,b++;//第一行没放石头,可放的行数减1
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",kase,sum);
}
return 0;
}
在一个m行n列的矩形网格里放k个相同的石子, 问有多少种方法? 每
个格子最多放一个石子, 所有石子都要用完, 并且第一行、 最后一行、
第一列、 最后一列都得有石子。
【输入格式】
输入第一行为数据组数T(T≤50) , 每组数据包含3个整数m,
n,
k(2≤m,
n≤20, k≤500) 。
【输出格式】
对于每组数据, 输出方案总数除以1000007的余数。
【分析】
如果题目求的是“第一行、 最后一行、 第一列、 最后一列都没有石
子”的方案数, 该有多好啊! 这相当于一共只有m-2行n-2列,
答案自然
是C((m-2) (n-2)
, k) 了。 幸运的是, 利用容斥原理, 我们可以
把本题转化为上述问题。
设满足“第一行没有石子”的方案集为A, 最后一行没有石子的方案集
为B, 第一列没有石子的方案集为C, 最后一列没有石子的方案集为D,
全集为S, 则所求答案就是“在S中但不在A,
B, C,
D任何一个集合中”的
元素个数, 可以用容斥原理求解。
在程序中, 我们用二进制来表示A,
B, C,
D的所有“搭配”(S对应
172
于“空搭配”) 。 如果在集合A和B中,
相当于少了一行; 如果在集合C或D
中, 相当于少了一列。 假定最后剩了r行c列, 方法数就是C(rc,
k) 。
#include<cstdio>
#include<iostream>
using namespace std;
const int mk=505,MOD=1000007;
int C[mk][mk];
int main()
{
//预处理出组合数
C[0][0]=1;
for(int i=1;i<mk;++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;
}
int T;
scanf("%d",&T);
for(int kase=1;kase<=T;++kase)
{
int n,m,k,sum=0;
scanf("%d%d%d",&n,&m,&k);
for(int S=0;S<16;++S)
{
int b=0,r=n,c=m;
if(S&1) r--,b++;//第一行没放石头,可放的行数减1
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",kase,sum);
}
return 0;
}
相关文章推荐
- 数学,容斥原理(拉拉队,uva 11806)
- UVa 11806 拉拉队(容斥原理)
- uva 11806 Cheerleaders 容斥原理
- uva 11806 Cheerleaders【容斥原理】
- UVA 11806 Cheerleaders 拉拉队
- 【递推】【组合数】【容斥原理】UVA - 11806 - Cheerleaders
- UVa 11806 Cheerleaders 拉拉队
- UVA.11806 Cheerleaders (组合数学 容斥原理 二进制枚举)
- uva11806(容斥原理)
- UVa11806 - Cheerleaders(容斥原理+状态压缩)
- uva 11806 容斥原理
- uva 11806 Cheerleaders (容斥原理)
- UVA 11806(B)——Cheerleaders 容斥原理 离散数学列举所有情况
- UVA 11806 - Cheerleaders (容斥原理)
- UVA 11806 - Cheerleaders(数论+容斥原理)
- UVA 11806 容斥原理
- UVA 11806 Cheerleaders(容斥原理)(组合数)
- UVA 11806 Cheerleaders (容斥原理)
- UVa 11806 Cheerleaders (数论容斥原理)
- uva11806 - Cheerleaders 容斥原理