P1350题解

我们来看一下这道题:

  1. 我们把图形分为 $(a, b)$ 与 $(a + c, d)$ 的矩阵

  2. 分别在两个矩阵放 $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;
}  
posted @ 2021-07-09 18:01  wangzhongyuan  阅读(2)  评论(0编辑  收藏  举报  来源