计蒜客——T3224

计蒜客T3224

有n个黑球,m个白球,n个箱子,把球都放进去,黑白不能放一起,问方案数。

如果没白球,就是把n个黑球放进n个箱子(可以空),就是C(n + n - 1, n - 1)

如果黑白都有,

先取 i 个箱子 (1 <= i < n,不能等于n,因为至少有一个箱子放白球),C(n, i)

然后把n个黑球放进i个箱子,不留空箱子,C(n - 1, i - 1)

然后把m个白球放进剩下 n - i 个箱子, 可以有箱子剩下,C(m + n - i - 1, n - i - 1)

阶乘有点大,要预处理一下,除法不能取模,要先求逆元。

求逆元参照这个

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 2e6 + 5;
const ll p = 998244353;

ll f[maxn], inv[maxn];

ll c(ll n, ll m) {
    if (n < m) return 0;
    return f[n] * inv[m] % p * inv[n - m] % p;
}

void pre(int len) {
    f[0] = f[1] = 1;
    for (int i = 1; i <= len; i++) {
        f[i] = f[i - 1] * i % p;
    }
    inv[0] = 1, inv[1] = 1;
    for (int i = 2; i <= len; i++) {
        inv[i] = (p - p / i) * inv[p % i] % p;
    }
    for (int i = 2; i <= len; i++) {
        inv[i] = inv[i - 1] * inv[i] % p;
    }
}

int main()
{
    ll n, m;
    cin >> n >> m;
    if (m == 0) {
        pre(n + n);
        cout << c(n + n - 1, n - 1);
        return 0;
    }
    pre(n + m);
    ll ans = 0;
    for (int i = 1; i < n; i++) {
        ll tmp = c(n, i) * c(n - 1, i - 1) % p * c(m + n - i - 1, n - i - 1) % p;
        ans = (ans % p) + (tmp % p) % p;
    }
    cout << ans % p << "
";
    return 0;
}
View Code

注意各种地方的取模...有些在预处理的时候就模过了

原文地址:https://www.cnblogs.com/zny0222/p/14337483.html