You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
3.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int mod = 1000007;
const int N = 410;
int C[N][N];
int n, m, k, ans;
/*
Sample Input
2
2 2 1
2 3 2
Sample Output
Case 1: 0
Case 2: 2
*/
int main() {
#ifndef ONLINE_JUDGE
freopen("UVA11806.in", "r", stdin);
#endif
// 预处理出组合数结果数组
for (int i = 1; i < 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;
}
int T, cas = 1;
int S, s1, s2, s3, s4;
cin >> T;
while (T--) {
ans = 0; // 多组测试数据,每次注意清零
cin >> n >> m >> k; // n行,m列,k个人
if (k == 0) { // 一定要注意边界情况比如0个人
printf("Case %d: 0\n", cas++);
continue;
}
S = C[n * m][k]; // n*m个格子中找出k个格子站人就是所有方案数
/*
S为总数
A为第一行没有站人
B为最后一行没有站人
C为第一列没有站人
D为最后一列没有站人
令:
s1 =(A+B+C+D)
s2=(AB+AC+AD+BC+BD+CD)
s3=(ABC+ABD+ACD+BCD)
s4=(ABCD)
*/
// A:第一行没人即C[(n-1)*m,k]
// B:最后一行没人,即C[(n-1)*m,k]
// C:第一列没人C[n*(m-1),k]
// D:最后一列没人C[n*(m-1),k]
s1 = 2 * (C[n * (m - 1)][k] + C[(n - 1) * m][k]) % mod;
// AB:第一行最后一行没有人行少了2行列不变即C[(n-2)*m,k]
// AC:第一行第一列没有人行少了1行列少了一列即C[(n-1)*(m-1),k]
// AD:第一行最后一列没有人即C[(n-1)*(m-1),k]
// BC:最后一行第一列没有人即C[(n-1)*(m-1),k]
// BD:最后一行,最后一列没有人,即C[(n-1)*(m-1),k]
// CD:第一列,最后一列没有人,即C[n*(m-2),k]
// 中间4个是一样的4*C[(n-1)*(m-1),k]
s2 = (C[(n - 2) * m][k] + 4 * C[(n - 1) * (m - 1)][k] + C[n * (m - 2)][k]) % mod;
// ABC:第一行、最后一行、第一列没有人行少了2行列少了1列即C[(n-2)*(m-1),k]
// ABD:第一行、最后一行、最后一列没有人行少了2行列少了1列即C[(n-2)*(m-1),k]
// ABC+ABD=2*C[(n-2)*(m-1),k]
// ACD:第一行、第一列、最后一列没有人行少了1行列少了2列即 C[(n-1)*(m-2),k]
// BCD:最后一行、第一列、最后一列没有人行少了1行列少了2列即 C[(n-1)*(m-2),k]
// ACD+BCD=2*C[(n-1)*(m-2),k]
s3 = 2 * (C[(n - 2) * (m - 1)][k] + C[(n - 1) * (m - 2)][k]) % mod;
// 第一行第一列最后一行最后一列都不能站那么剩下n-2行m-2列需要在(n-2)*(m-2)这么多的格子里找出k个格子
s4 = C[(n - 2) * (m - 2)][k] % mod;
ans = (S - s1 + s2 - s3 + s4) % mod; // 容斥原理
ans = (ans + mod) % mod; // 防止取余后出现负数
printf("Case %d: %d\n", cas++, ans); // 输出答案
}
return 0;
}