P1350 车的放置 [排列组合]

P1350 车的放置

递推不会,只会排列组合。。。

我们把原来的这个棋盘分成两个小矩形棋盘,然后计算方案数。

设在上面放了\(i\)个棋子,那么就必须在下面放\(k-i\)个棋子。

先在上面的矩形放置,方案数是\(C_a^i \times C_b^i\times i!\)

但是下面的矩形就需要考虑上面矩形的限制了:已经放过的列就不能再放。

所以在下面放置的方案数是\(C_{a+c-i}^{k-i} \times C_d^{k-i} \times (k-i)!\)\(i\)的意义不变)

考虑所有上下都合法的\(i\),相加即为答案。

代码:

/*************************************************************************
 @Author: Garen
 @Created Time : Sat 23 Feb 2019 04:46:27 PM CST
 @File Name: P1350.cpp
 @Description:
 ************************************************************************/
#include<bits/stdc++.h>
using std::cin;
using std::cout;
using std::endl;
#define ll long long
const ll MOD = 100003;
const ll maxn = 100005;
ll a, b, c, d, k;
ll ans;
ll frac[maxn];
ll ans1[maxn], ans2[maxn];
ll pow_mod(ll x, ll y) {
    ll ans = 1; x %= MOD;
    while(y) {
        if(y & 1) ans = ans * x % MOD;
        x = x * x % MOD;
        y >>= 1;
    }
    return ans % MOD;
}
inline ll inv(ll p) {
    return pow_mod(p, MOD - 2);
}
ll C(ll m, ll n) {
    return frac[m] * inv(frac[n]) % MOD * inv(frac[m - n]) % MOD;
}
int main() {
    frac[0] = 1;
    for(ll i = 1; i <= 100000; i++) frac[i] = frac[i - 1] * i % MOD;
    cin >> a >> b >> c >> d >> k;
    // divide the graph into two parts
    // first part: a * b
    // second part: (a + c) * d
    for(ll i = 0; i <= std::min(a, std::min(b, k)); i++) {
        ans1[i] = C(a, i) * C(b, i) % MOD * frac[i] % MOD;
        //cout << ans1[i] << endl;
    }
    for(ll i = 0; i <= std::min(a + c, std::min(d, k)); i++) {
        ans2[i] = C(a + c - (k - i), i) * C(d, i) % MOD * frac[i] % MOD;
        //cout << ans2[i] << endl;
    }
    for(ll i = 0; i <= k; i++) {
        ans = (ans + ans1[i] * ans2[k - i] % MOD) % MOD;
    }
    cout << ans << endl;
    return 0;
}

参考文献:https://www.cnblogs.com/ZUTTER/p/9881500.html

比我讲的好多了,还有图。去那里看8

猜你喜欢

转载自www.cnblogs.com/Garen-Wang/p/10423509.html