// uva 11806 Cheerleaders // // 题目大意: // // 给你n * m的矩形格子,要求放k个相同的石子,使得矩形的第一行 // 第一列,最后一行,最后一列都必须有石子. // // 解题思路: // // 容斥原理,我们这样考虑,如果只是n * m放石子,那么最后的结果 // 就是C(n*m,k).我们设A为第一行不放石头的总数,B为最后一行不放石子 // 的总数,C为第一列不放石子的总数,D为最后一列不放石子的总数.则问题 // 转化为在全集S中,求不在A,B,C,D部分的解.则答案为S - | A | - | B | // - | C | - | D | + | A ^ B|......用一个二进制枚举状态,统计就可以了 // // 感悟: // // 这道题,开始的时候,从正面做,看减去什么,但是最后都是把自己脑子搞糊涂 // 了,不知道自己在干什么,最后,就没有最后了,每次做题,都是这种感觉,看到解答 // 的时候,我才恍然大悟,原来可以这样啊,自己缺乏抽象思维,缺乏转换问题的思维 // 多说也没什么用,继续加油吧!FIGHTING #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long ll; const int MAX_N = 500; const ll MOD = 1000007; ll C[MAX_N][MAX_N]; int n,m,k; void init(){ C[0][0] = 1; for (int i=1;i<MAX_N;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; } } void input(){ scanf("%d%d%d",&n,&m,&k); ll sum = 0; for (int S=0;S<16;S++){ int b = 0,r = n,c = m; if(S & 1){ r--; b++; } if (S & 2){ r--; b++; } if (S & 4){ c--; b++; } if (S & 8){ c--; b++; } if (b & 1) sum = (sum + MOD - C[r * c][k])%MOD; else sum = (sum + C[r * c][k])%MOD; } cout << sum << endl; } int main(){ int t; init(); //freopen("1.txt","r",stdin); scanf("%d",&t); int kase = 1; while(t--){ printf("Case %d: ",kase++); input(); } }
浙公网安备 33010602011771号