题目大意:
在 T 个样例中,有 M*N 的矩阵,准确地染色 K 个块,使得矩阵首行、末行、首列、末列都有块被染色,输出其可能数
分类讨论:
按四角的染色情况为分类依据,以4*5的矩阵为例
1.
如图(后面的图解都按同一规则绘制,叉表示不放置,黑色表示放置,橙色表示该区域必放置一个,青色表示不必放置但可以放置)。
若 区域上放置x1个,区域下放置x2个,区域左放置x3个,区域右放置x4个,区域中放置x5个,则有:
1<=x1<=3,1<=x1<=3,1<=x1<=2,1<=x1<=2,0<=x1<=6
且x1+x2+x3+x4+x5=K,是带位置的不定方程,这样有一种情况。2.
如放置情况如上,则有:
0<=x1<=3,1<=x1<=3,0<=x1<=2,1<=x1<=2,0<=x1<=6
且x1+x2+x3+x4+x5=K-1,也是带位置的不定方程,这样有四种情况。3.
如放置情况如上,则有:
0<=x1<=3,0<=x1<=3,0<=x1<=2,1<=x1<=2,0<=x1<=6
且x1+x2+x3+x4+x5=K-2,也是带位置的不定方程,这样有两种情况。4.
如放置情况如上,则有:
0<=x1<=3,1<=x1<=3,0<=x1<=2,0<=x1<=2,0<=x1<=6
且x1+x2+x3+x4+x5=K-2,也是带位置的不定方程,这样有两种情况。5.
如放置情况如上,则有:
0<=x1<=3,0<=x1<=3,0<=x1<=2,0<=x1<=2,0<=x1<=6
且x1+x2+x3+x4+x5=K-2,也是带位置的不定方程,这样有两种情况。6.
如放置情况如上,则有:
0<=x1<=3,0<=x1<=3,0<=x1<=2,0<=x1<=2,0<=x1<=6
且x1+x2+x3+x4+x5=K-3,也是带位置的不定方程,这样有四种情况。7.
如放置情况如上,则有:
0<=x1<=3,0<=x1<=3,0<=x1<=2,0<=x1<=2,0<=x1<=6
且x1+x2+x3+x4+x5=K-4,也是带位置的不定方程,这样有一种情况。
所以这道题目实际上可以由7中规律性相同的函数计算求和得到。
对于带位置的不定方程,有这么几个参数:
不定元x1,x2,x3,x4,x5,不定元的左界l1,l2,l3,l4,l5,不定元的右界r1,r2,r3,r4,r5,不定元可使用的空间数b1,b2,b3,b4,b5,不定方程的本体x1+x2+x3+x4+x5=K,由K标记。
可以使用的状态转移:
A[i][j]表示使用前i个不定元达到的K值j时不定方程的解数
初始状态:A[0][0]=1,A[0][i]=0,K>=i>0
转移方程:
下附AC 代码
#pragma warning(disable:4996)
#include<cstdio>
int T, M, N, K;
int R[6], B[6], L[6];
long long sum;
#define MOD 1000007
#define MAXN 510
long long Yong[MAXN][MAXN];
void YongInitial() {
Yong[0][0] = 0;
Yong[0][1] = 1;
Yong[0][2] = 1;
Yong[0][3] = 0;
for (int i = 1; i < MAXN; i++) {
Yong[i][0] = 0;
Yong[i][i + 3] = 0;
for (int j = 1; j <= i + 2; j++) {
Yong[i][j] = Yong[i - 1][j - 1] + Yong[i - 1][j];
if (Yong[i][j] >= MOD) {
Yong[i][j] -= MOD;
}
}
}
}
inline long long C(int m, int k) {
if (m < k) {
return 0;
}
if (m == 0) {
return 1;
}
return Yong[m - 1][k + 1];
}
long long DP[6][MAXN];
long long ADP(int K) {
if (K < 0) {
return (long long)0;
//special output
}
for (int i = 0; i <= K; i++) {
DP[0][i] = 0;
}
DP[0][0] = 1;
for (int i = 1; i < 6; i++) {
for (int j = 0; j <= K; j++) {
DP[i][j] = 0;
for (int t = 0; t <= j; t++) {
if (t < L[i - 1]) {
continue;
}
if (t > R[i - 1]) {
break;
}
DP[i][j] += DP[i - 1][j - t] * C(B[i-1], t);
DP[i][j] %= MOD;
}
}
}
return DP[5][K];
}
long long ADD(int K) {
long long sum;
sum = 0;
R[0] = B[0] = M - 2;
R[1] = B[1] = M - 2;
R[2] = B[2] = N - 2;
R[3] = B[3] = N - 2;
L[0] = L[1] = L[2] = L[3] = 1;
//mid
R[4] = B[4] = (M - 2) * (N - 2);
L[4] = 0;
sum += ADP(K);
L[0] = L[2] = 0;
sum += ADP(K - 1) * 4;
L[3] = 0;
sum += ADP(K - 2) * 2;
L[3] = 1;
L[1] = 0;
sum += ADP(K - 2) * 2;
L[3] = 0;
sum += ADP(K - 2) * 2;
sum += ADP(K - 3) * 4;
sum += ADP(K - 4);
sum %= MOD;
return sum;
}
int main() {
YongInitial();
scanf("%d", &T);
for (int i = 1; i <= T; i++) {
sum = 0;
scanf("%d%d%d", &M, &N, &K);
sum = ADD(K);
printf("Case %d: %lld\n", i, sum);
}
}