P1350题解
我们来看一下这道题:
-
我们把图形分为 $(a, b)$ 与 $(a + c, d)$ 的矩阵
-
分别在两个矩阵放 $i$ 与 $k - i$ 个车
定义 $f(n, m, i)$ 表示在 $(n, m)$ 的矩阵中放 $i$ 个的方案数
讲解到此为止!
$ans = \sum\limits_{i=0}^k (f(a, b, i) \times f(a + c - i, d, k - i))$
注:上式中的 $a + c - i$ 是为了避免在同一行
问题来了,怎么求 $f(n, m, i)$ :
-
在 $(n, m)$ 中取出 $k$ 行放车: $\dbinom{n}{k}$
-
在 $(n, m)$ 中取出 $k$ 列放车: $\dbinom{m}{k}$
-
再在已取得 $k$ 行与 $k$ 列中选 $k$ 个车:$\dbinom{k}{k} = k!$
所以 $f(n, m, i) = k!\dbinom{n}{k}\dbinom{m}{k}$
$\dbinom{n}{m}$ 的求法可用Lucas定理
若不会,可以前往 这里 学习
代码部分:
#include <iostream>
using namespace std;
#define int long long // 偷懒写法qwq
const int mod = 100003, maxn = 3010;
int inv[maxn];
int pow (int x, int y) { //快速幂
int res = 1;
while (y) {
if (y % 2 == 1) {
res = res * x % mod;
}
x = x * x % mod;
y /= 2;
}
return res;
}
int C (int n, int m) {
if (n < m) return 0;
if (m > n - m) m = n - m;
int sum1 = 1, sum2 = 1;
for(int i = 0; i < m; ++i){
sum1 = sum1 * (n - i) % mod;
sum2 = sum2 * (i + 1) % mod;
}
return sum1 * pow (sum2, mod - 2) % mod;
}
int Lucas(int n, int m){ //Lucas 求组合数
if (m == 0) return 1;
return C (n % mod, m % mod) * Lucas (n / mod, m / mod) % mod;
}
int f (int n, int m, int k) {
if (n < k || m < k) return 0;
return 1ll * Lucas (n, k) * Lucas (m, k) % mod * inv[k] % mod;
}
signed main() {
int a, b, c, d, k, ans = 0;
scanf ("%lld%lld%lld%lld%lld", &a, &b, &c, &d, &k);
inv[0] = 1;
for (int i = 1; i < maxn; ++i) {
inv[i] = inv[i - 1] * i % mod;
} // 求 i!
for (int i = 0; i <= k; ++i) {
ans += 1ll * f (a, b, i) * f (a + c - i, d, k - i) % mod;
ans %= mod; //不要忘记取模哦!
}
printf ("%lld", ans);
return 0;
}