于是考虑设计这么一个状态 f[i][j][k]
f
[
i
]
[
j
]
[
k
]
,表示用前 k
k
种颜色的棋子占领了任意 i 行 j
j
列的方案数,则:(假设第 k 种棋子有 a[k]
a
[
k
]
枚)f[i][j][k]=∑l=0i−1∑r=0j−1f[l][r][k−1]×用a[k]枚棋子占领(i−l)行(j−r)列的方案数×Ci−ln−l×Cj−rm−r((i−l)×(j−r)≥a[k])
f
[
i
]
[
j
]
[
k
]
=
∑
l
=
0
i
−
1
∑
r
=
0
j
−
1
f
[
l
]
[
r
]
[
k
−
1
]
×
用
a
[
k
]
枚
棋
子
占
领
(
i
−
l
)
行
(
j
−
r
)
列
的
方
案
数
×
C
n
−
l
i
−
l
×
C
m
−
r
j
−
r
(
(
i
−
l
)
×
(
j
−
r
)
≥
a
[
k
]
)
其它都好处理,但“用 a[k]
a
[
k
]
枚棋子占领 (i−l)
(
i
−
l
)
行 (j−r)
(
j
−
r
)
列的方案数”似乎不是那么容易直接求。
考虑再设一个状态 g[i][j][k]
g
[
i
]
[
j
]
[
k
]
,表示任意 k
k
枚同色棋子占领了任意 i 行 j
j
列的方案数,通过一些转换,我们可以得到:
我们预处理 g[i][j][k]
g
[
i
]
[
j
]
[
k
]
,则 f[i][j][k]
f
[
i
]
[
j
]
[
k
]
的转移就可表示为:f[i][j][k]=∑l=0i−1∑r=0j−1f[l][r][k−1]×g[i−l][j−r][a[k]]×Ci−ln−l×Cj−rm−r((i−l)×(j−r)≥a[k])
f
[
i
]
[
j
]
[
k
]
=
∑
l
=
0
i
−
1
∑
r
=
0
j
−
1
f
[
l
]
[
r
]
[
k
−
1
]
×
g
[
i
−
l
]
[
j
−
r
]
[
a
[
k
]
]
×
C
n
−
l
i
−
l
×
C
m
−
r
j
−
r
(
(
i
−
l
)
×
(
j
−
r
)
≥
a
[
k
]
)
不一定要每行每列都占领,但棋子要全放完,答案就为 ∑i=1n∑j=1mf[i][j][c]
∑
i
=
1
n
∑
j
=
1
m
f
[
i
]
[
j
]
[
c
]
。
时间复杂度 O(n2m2c)
O
(
n
2
m
2
c
)
。
Code
#include <iostream>#include <cstdio>#include <cstring>usingnamespacestd;
typedeflonglong ll;
constint Mod = 1e9 + 9;
constint N = 35, M = 15, L = 905;
int g[N][N], f[N][N][M], c[L][L];
int x, n, m, C, Ans;
int main()
{
// freopen("chess.in", "r", stdin);// freopen("chess.out", "w", stdout);scanf("%d%d%d", &n, &m, &C);
constint tmp = n * m;
for (int i = 0; i <= tmp; ++i)
c[i][0] = 1;
for (int i = 1; i <= tmp; ++i)
for (int j = 1; j <= i; ++j)
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % Mod;
f[0][0][0] = 1;
for (int k = 1; k <= C; ++k)
{
scanf("%d", &x);
memset(g, 0, sizeof(g));
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (i * j >= x)
{
g[i][j] = c[i * j][x];
for (int l = 1; l <= i; ++l)
for (int r = 1; r <= j; ++r)
if (l < i || r < j)
g[i][j] = ((ll)g[i][j] - (ll)g[l][r]
* c[i][l] % Mod * c[j][r] % Mod + Mod) % Mod;
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
for (int l = 0; l < i; ++l)
for (int r = 0; r < j; ++r)
{
int tx = i - l, ty = j - r;
if (tx * ty >= x)
(f[i][j][k] += (ll)f[l][r][k - 1] * g[tx][ty] % Mod
* c[n - l][tx] % Mod * c[m - r][ty] % Mod) %= Mod;
}
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
(Ans += f[i][j][C]) %= Mod;
printf("%d\n", Ans);
// fclose(stdin); fclose(stdout);return0;
}