您的位置:首页 > 其它

Uva11806——容斥原理

2013-03-13 16:48 232 查看
题意:给出一个n*m个单元组成的矩形,在其中k个单元涂色,并且每条边上一定至少一个被涂色,求涂色的方案数。

如果直接分析,对于四个角上的单元和四条边上的单元有太多的情况要考虑;如果硬着头皮把所有情况枚举,那这个代码基本是不可能完成的。其实可以反过来想:问题的反面是求至少有一条边没被涂色的方案数。一般来说,计数问题中看到“至少有一”这个词的时候,就可对应到某一些子集的并集,我们可以把“至少”拿掉:求有一条边没有被涂色的方案数,而矩形一共4条边,也即对应到4个子集。同时这4个子集任意若干个的交集也是很好计算的,所以这4个子集的并集是很方便用容斥原理计算出来的,再对其求全集的补集就是答案了。

#include <iostream>
#include <cstdio>
#define lng long long
using namespace std;

const int mod = 1000007;
int C[1000][1000];
int n, m, k;

void init()
{
C[0][0] = 1; C[1][0] = 1; C[1][1] = 1;
for(int i = 2; i <= 500; ++i)
{
C[i][0] = 1;
for(int j = 1; j <= i; ++j)
{
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
C[i][j] %= mod;
}
}
}

int main()
{
init();
freopen("in.txt", "r", stdin);
int t; scanf("%d", &t); int cc = 1;
while(t--)
{
scanf("%d %d %d", &n, &m, &k);
int res = 0, squ = m * n;
res += C[squ - m][k] * 2; res += C[squ - n][k] * 2; res %= mod;
res -= (C[squ - 2 * m][k] + C[squ - 2 * n][k] + 4 * C[squ - m - n + 1][k]) % mod;
if(res < 0) res += mod;
res += (2 * C[(m - 2) * (n - 1)][k] + 2 * C[(n - 2) * (m - 1)][k]) % mod; res %= mod;
res -= C[(m - 2) * (n - 2)][k];
if(res < 0) res += mod;
res = (C[squ][k] - res) % mod;
if(res < 0) res += mod;
printf("Case %d: %d\n", cc++, res);
}
return 0;
}

/*
2
2 2 1
2 3 2

Case 1: 0
Case 2: 2

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: