uva11806Cheerleaders--容斥原理

题目链接:

点击打开链接

题目意思:

在一个m行n列的矩形方格里放置k个相同的石子,每个格最多放一个石子,所有石子都要放完,并且第一行,最后一行,第一列,最后一列都得有石子,问一共有多少种放法?

题目分析

一开始想到的是分类,但是由于四个角上的棋子分类比较复杂,就放弃了。后来想到了容斥原理。

设满足“第一行没有石子”的方案为A,满足“第最后一行没有石子”的方案为B,满足“第一列没有石子”的方案为C,满足“第最后一列没有石子”的方案为D。在程序中利用二进制来表示ABCD的所有搭配,并满足”奇减偶加“。

AC代码

#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;

const int maxn = 500;
const int mod = 1000007;
int c[maxn+10][maxn+10];

int main()
{
    int t,m,n,k;
    memset(c,0,sizeof(c));
    c[0][0] = 1;
    for(int i=0;i<=maxn;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 cnt = 0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&m,&n,&k);
        int sum = 0;
        for(int s=0;s<=15;s++)
        {
            int h = m;   //h,l的赋值在for循环内部,hl表示行列数
            int l = n;
            int b = 0;
            if(s & 1)  {h--; b++;}  //表示组合中有A,下面以此类推
            if(s & 2)  {h--; b++;}
            if(s & 4)  {l--; b++;}
            if(s & 8)  {l--; b++;}
            if(b & 1) //奇数
                sum = (sum + mod-c[l*h][k])%mod;  //加上取余的数,避免产生负值
            else
                sum = (sum + c[l*h][k]) % mod;
        }
        printf("Case %d: %d\n",++cnt,sum);
    }
    return 0;
}

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