UVa:11806 Cheerleaders

白书上的例题,跟LRJ写的基本一样。

注意组合数的递推,这里写错WA了一次。

用到了容斥原理,需要各种情况的组合,用二进制枚举子集,由于是从全集里面扣掉,所以奇变成了减,偶变成了加。感觉还是很厉害。。

取余的时候如果有减法,要记得加一个模,避免出现负数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#define ll long long
#define INF 200000000
#define MOD 1000007
#define MAXN 4000*1005
using namespace std;
int C[505][505];
void Init()
{
    for(int i=0; i<=500; ++i)
    {
        C[i][0]=C[i][i]=1;
        for(int j=1; j<i; ++j)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
    }
}
int main()
{
    int T,kase=0;
    scanf("%d",&T);
    Init();
    while(T--)
    {
        int N,M,K;
        scanf("%d%d%d",&M,&N,&K);
        int sum=0;
        for(int i=0; i<16; ++i)
        {
            int a=0,b=M,c=N;
            if(i&1)
            {
                a++;
                b--;
            }
            if(i&2)
            {
                a++;
                b--;
            }
            if(i&4)
            {
                a++;
                c--;
            }
            if(i&8)
            {
                a++;
                c--;
            }
            if(a&1) sum=(sum-C[b*c][K]+MOD)%MOD;
            else sum=(sum+C[b*c][K])%MOD;
        }
        printf("Case %d: %d\n",++kase,sum);
    }
    return 0;
}


 

你可能感兴趣的:(容斥原理)