---
# System prepended metadata

title: Free Contest 130 - MERGE
tags: [' Free Contest', VNOJ, ' Math', ' Combinatorics', ' SPyofgame', ' kazamahoang']

---

---
tags: VNOJ, Free Contest, Combinatorics, Math, SPyofgame, kazamahoang
---


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)

###### Tags: `Combinatorics`, `Math`

-----

### 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 $S$ gồm các phần tử trộn 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

```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;
}
```