E Cheerleaders (UVA 11806)




题目大意:

就是给定一个 n * m 的方格,然后在这个方格中 放入k个石子有几种方法,条件限制是要求第一行,第一列,最后一行,最后一列必须有石子。

解题思路:

这个可以考虑容斥原理,就是总数减去 第一行,第一列,最后一行,最后一列 没有石子的数目,现在假设 

事件A: 第一行没有石子;

事件B: 第一列没有石子;

事件C: 最后一行没有石子;

事件D: 最后一列没有石子;

则我们需要求的方法数:= C(n*m,k) - AUBUCUD; AUBUCUD = |A| + |B| + |C| + |D| - |AB| - |BC| - |AC| - |AD| - |BD| - |CD| + |ABC| + |ABD| + |ACD| + |BCD| - |ABCD|,我们写程序的时候可以借助二进制来表示 集合,然后枚举就行了...

还要注意的是 先打一个表,将组合数打出来

My Code:

<span style="font-size:18px;">#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int MAXN = 505;
const int MOD = 1000007;
int mat[MAXN][MAXN];
void Init()
{
    memset(mat, 0, sizeof(mat));
    mat[0][0] = 1;
    for(int i=1; i<MAXN; i++)
    {
        mat[i][0] = mat[i][i] = 1;
        for(int j=1; j<i; j++)
        {
            mat[i][j] = mat[i-1][j-1] + mat[i-1][j];
            mat[i][j] %= MOD;
        }
    }
}
int main()
{
    Init();
    int T, n, m, k;
    cin>>T;
    for(int cas=1; cas<=T; cas++)
    {
        cin>>n>>m>>k;
        int ans = 0;
        for(int i=0; i<(1<<4); i++)
        {
            int j = 0, r = n, c = m;
            if(i & 1)
            {
                r--;
                j++;
            }
            if(i & 2)
            {
                r--;
                j++;
            }
            if(i & 4)
            {
                c--;
                j++;
            }
            if(i & 8)
            {
                c--;
                j++;
            }
            if (j & 1)
                ans = (ans + MOD - mat[r*c][k])%MOD;
            else
                ans = (ans + mat[r*c][k])%MOD;
        }
        printf("Case %d: %d\n",cas,ans);
    }
    return 0;
}
</span>


你可能感兴趣的:(E Cheerleaders (UVA 11806))