题目描述
https://codeforces.com/problemset/problem/869/C
Solution
我们不妨先考虑只有两个区域的情况
令两个区域的点的个数分别为 $n$ 和 $m$,不妨令 $n\le m$
则我们发现每个点只能连一条边,所以答案显然为 $\sum_{i=0}\binom{n}{i}\binom{m}{i}i!$
然后我们在思考三个区域的情况,注意到同色点的最短距离至少为 $3$
也就是说不能出现两个同色点连同一个点以及同色点之间相连的情况
那么三个区域 $a,b,c$ 就能拆成 $a,b$,$b,c$,$a,c$,它们之间的连边是互不影响的
所以我们直接将三部分的答案乘起来即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <iostream> #include <cstdio> #include <map> #include <algorithm> #include <vector> #include <set> #define maxn 5010 #define ll long long using namespace std;
const int p = 998244353;
ll pow_mod(ll x, ll n) { ll s = 1; for (; n; n >>= 1) { if (n & 1) s = s * x % p; x = x * x % p; } return s; }
int a, b, c;
ll fac[maxn], inv[maxn]; void init_C(int n) { fac[0] = 1; for (int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i % p; inv[n] = pow_mod(fac[n], p - 2); for (int i = n - 1; ~i; --i) inv[i] = inv[i + 1] * (i + 1) % p; }
inline ll C(int n, int m) { return n < m ? 0 : fac[n] * inv[m] % p * inv[n - m] % p; }
ll get(int n, int m) { ll s = 0; if (n > m) swap(n, m); for (int i = 0; i <= n; ++i) s = (s + C(n, i) * C(m, i) % p * fac[i]) % p; return s; }
ll ans; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> a >> b >> c; init_C(5000); cout << get(a, b) * get(a, c) % p * get(b, c) % p << "\n"; return 0; }
|