【UVA11806】Cheerleaders——容斥

题意:给你一个 n×m 的矩阵网格和k个人,问有多少种方法使得每一个格子只放一个人,并且第一行,最后一行,第一列,最后一列都有人。

分析:如果没有限制条件,我们知道答案是 ans=C(nm,k),ABCD
ans=ansABCD+AB+AC+AD+ABCD

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const LL Mod = 1000007;

LL C[500][500];

void Init()//提前计算好组合数
{
    memset(C,0,sizeof(C));

    C[0][0]  =1;

    for(int i = 1;i<500;i++)
    {
        C[i][0 ] =C[i][i] =1 ;

        for(int j = 1;j<i;j++)
        {
            C[i][j] = (C[i-1][j]+C[i-1][j-1])%Mod;

        }
    }

}

int main()
{
    int T;

    LL n,m,k;

    Init();

    scanf("%d",&T);

    for(int z = 1;z<=T;z++)
    {
        scanf("%lld %lld %lld",&n,&m,&k);

        LL ans = 0 ;

        for(int i = 0;i<(1<<4);i++)//枚举组合的情况
        {
            LL num = 0;

            int L = n,R = m;

            for(int j = 0;j<4;j++)
            {
                if(i&(1<<j))
                {
                    num++;

                    if(j==0||j==1)
                    {
                        L--;
                    }
                    else 
                    {
                        R--;
                    }
                }
            }

            if(num%2)
            {
                ans = (ans+Mod-C[L*R][k])%Mod;
            }
            else
            {
                ans = (ans+C[L*R][k])%Mod;
            }

        }

        cout<<"Case "<<z<<": "<<ans<<endl;
    }
    return 0;
}

你可能感兴趣的:(【UVA11806】Cheerleaders——容斥)