Free Contest 130 - MERGE === [https://oj.vnoi.info/problem/fc130_merge](https://oj.vnoi.info/problem/fc130_merge) ----- **Contributor:** [@jalsol](https://codeforces.com/profile/jalsol) [@volongskl2003](https://codeforces.com/profile/volongskl2003) ----- ### Hướng dẫn Xét các tập: - $A = \{1, 2, \dots, n\}$ - $B = \{n + 1, n + 2, \dots, n + m\}$ - $C = \{n + m + 1, n + m + 2, \dots, n + m + k\}$ **Nhận xét 1:** Đề yêu cầu số tìm cách chọn một tập con $S$ từ 3 tập $A, B, C$ sao cho các phần tử cùng một tập được chọn phải sắp xếp tăng dần. Nên việc chọn các số giữa các tập là độc lập nhau. **Nhận xét 2:** Số cách để chọn một tập con $S$ bất kì là $x = (n + m + k)!$ - Trong số đó, chỉ có $\frac{x}{n!}$ tập có các phần tử trong tập $A$ sắp xếp tăng dần. - Trong số đó, chỉ có $\frac{x}{m!}$ tập có các phần tử trong tập $B$ sắp xếp tăng dần. - Trong số đó, chỉ có $\frac{x}{k!}$ tập có các phần tử trong tập $C$ sắp xếp tăng dần. Vì việc chọn các tập là độc lập nhau (nhận xét 1), ta có số tập con $S$ thỏa cả 3 tính chất trên là $\frac{(n + m + k)!}{n! \times m! \times k!}$ Vậy kết quả bài toán là $\frac{(n + m + k)!}{n! \times m! \times k!} \bmod (10^9 + 7)$ --- Để tính $x^n$ nhanh ta tính $x^n$ dựa trên $x^{n/2}$ hoặc dùng thuật toán lũy thừa nhị phân. Để tính $\frac{1}{a!}$ dưới một modulo nguyên tố $b$ mà không cần xử lí số lớn ta áp dụng định lí nhỏ fermat ta có $\frac{1}{a!} = a!^{-1} \large \equiv \normalsize a!^{b - 2} \pmod b$ ----- ### Code > For constant modulo $MOD = 10^9 + 7$ > **Time:** $O(n + m + k + 3\log_2(MOD))$ > **Space:** $O(n + m + k)$ > **Algo:** Combinatorics, Math, Binary Exponentiation ```cpp= #include <iostream> using namespace std; const int LIM = 3e6 + 36; const int MOD = 1e9 + 7; /// x^n % MOD in O(log n) int powMOD(int x, int n) { int res = 1; for (; n > 0; n >>= 1) { if (n & 1) res = (1LL * res * x) % MOD; x = (1LL * x * x) % MOD; } return res; } /// fact[n] = n! int fact[LIM]; int main() { int n, m, k; cin >> n >> m >> k; fact[0] = 1; for (int i = 1; i <= n + m + k; ++i) fact[i] = (1LL * fact[i - 1] * i) % MOD; /// n! = (n - 1)! * n int res = fact[n + m + k]; /// res := (n + m + k)! res = (1LL * res * powMOD(fact[n], MOD - 2)) % MOD; /// res := res / n! res = (1LL * res * powMOD(fact[m], MOD - 2)) % MOD; /// res := res / m! res = (1LL * res * powMOD(fact[k], MOD - 2)) % MOD; /// res := res / k! cout << res; return 0; } ```