Uva11806——容斥原理

题意:给出一个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

*/


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值