原题链接:AcWing1309
题目大意:有下面这样的一个网格棋盘,$a,b,c,d$ 表示了对应边长度,也就是对应格子数。

当 $a=b=c=d=2$ 时,对应下面这样一个棋盘:

要在这个棋盘上放 $k$ 个相互不攻击的车,也就是这 $k$ 个车没有两个车在同一行,也没有两个车在同一列,问有多少种方案。
只需要输出答案 $\mathrm{mod} \ 100003$ 后的结果。
输入格式
共一行,五个非负整数 $a,b,c,d,k$。
输出格式
包括一个正整数,为答案 $\mathrm{mod} \ 100003$ 后的结果。
数据范围
$1≤a,b,c,d,k≤1000$,
保证至少有一种可行方案。
输入样例
输出样例
组合计数
解法
思路:将原图分解成 $2$ 个部分,$a \times b$ 的矩形 $A$ 和 $(a+c) \times d$ 的矩形 $B$。
假设 $A$ 中放置 $i$ 个车,$B$ 中放置 $k-i$ 个车。$A$ 中需要从 $b$ 行中选 $i$ 行,再从 $a$ 列中选出 $i$ 列,即 $C_b^i \cdot A_a^i$;同样地,$B$ 中需要从 $d$ 行中选出 $k-i$ 行,选择列的时候,由于 $A$ 中已选的列,在 $B$ 中不可选,因此要再从 $B$ 中的 $a+c-i$ 列中选出 $k-i$ 列,即 $C_d^{k-i} \cdot A_{a+c-i}^{k-i}$
根据乘法原理和加法原理,答案为:
$$
\sum_{i=0}^{\min(a,b,k)}C_b^i \cdot A_a^i \cdot C_d^{k-i} \cdot A_{a+c-i}^{k-i}
$$
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2010, mod = 100003;
int a, b, c, d, k;
int fact[N], infact[N];
int ksm(int a, int k) {
int res = 1;
while (k) {
if (k & 1) res = (LL)res * a % mod;
a = (LL)a * a % mod;
k >>= 1;
}
return res;
}
void init() {
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i++) {
fact[i] = (LL)fact[i - 1] * i % mod;
infact[i] = (LL)infact[i - 1] * ksm(i, mod - 2) % mod;
}
}
int C(int a, int b) {
if (a < b) return 0;
return (LL)fact[a] * infact[b] % mod * infact[a - b] % mod;
}
int A(int a, int b) {
if (a < b) return 0;
return (LL)fact[a] * infact[a - b] % mod;
}
int main() {
init();
cin >> a >> b >> c >> d >> k;
LL res = 0;
int lim = min(min(a, b), k);
for (int i = 0; i <= lim; i++) {
(res += (LL)C(b, i) * A(a, i) % mod * C(d, k - i) % mod * A(a + c - i, k - i)) %= mod;
}
cout << res << endl;
return 0;
}
|