題目鏈接
題意:在一個m*n的矩形網格裡放k個相同的石子,問有多少種方法?每個格子最多放一個石子,所有石子都要放完,並且第一行、最後一行、第一列、最後一列都得有石子。
思路:假設滿足第一行沒有石子的方案集為A,最後一行沒有石子的方案集為B,第一列沒有石子的方案集為C,最後一列沒有石子的方案集為D,全集為S,則所求答案就是“在S中但不在A,B,C,D任何一個集合中”的元素個數,這裡就是運用容斥原理。程序中可以用二進制來表示集合。
代碼:
#include#include #include #include #include using namespace std; const int MAXN = 510; const int MOD = 1000007; int C[MAXN][MAXN]; int n, m, k; void init() { 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 main() { init(); int cas, t = 1; scanf("%d", &cas); while (cas--) { scanf("%d%d%d", &n, &m, &k); int sum = 0; for (int S = 0; S < 16; S++) { int b = 0, r = n, c = m; for (int i = 0; i < 4; i++) { if (S & (1 << i)) { if (i % 2) r--; else c--; b++; } } if (b & 1) sum = (sum + MOD - C[r * c][k]) % MOD; else sum = (sum + C[r * c][k]) % MOD; } printf("Case %d: %d\n", t++, sum); } return 0; }