#include 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; }