计蒜客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; }
注意各种地方的取模...有些在预处理的时候就模过了