## Các phép cộng, trừ, nhân
Đối với phép cộng ta có: $(a + b) \bmod m = (a \bmod m + b \bmod m) \bmod m$
Tương tự với phép trừ và nhân:
$(a - b) \bmod m = (a \bmod m - b \bmod m) \bmod m$
$(a \cdot b) \bmod m = ((a \bmod m) \cdot (b \bmod m)) \bmod m$
***Lưu ý:*** Vì kết quả có thể âm nhưng hầu như ta đều muốn kết quả của phép mod là dương nên ta sẽ cộng thêm m vào cuối:
$(a + b) \bmod m = ((a \bmod m + b \bmod m) \bmod m + m) \bmod m$
$(a - b) \bmod m = ((a \bmod m - b \bmod m) \bmod m + m) \bmod m$
$(a \cdot b) \bmod m = (((a \bmod m) \cdot (b \bmod m)) \bmod m + m) \bmod m$
<br>
## Tính $a^b \bmod m$
Ta cũng có thể dùng [lũy thừa nhị phân](https://hackmd.io/IsGwluMuQSuzeJ8NY0mEKw) kết hợp thêm $\bmod m$:
```cpp!
long long binpow(long long a, long long b, long long m) {
long long res = 1;
a %= m;
while(b > 0) {
if(b & 1)
res = res * a % m;
a = a * a % m;
b >>= 1;
}
return res;
}
```
## Phép chia
mod trong phép chia không giống với cộng, trừ, hay nhân, mà ta sẽ dùng tới một khái niệm mới: **nghịch đảo modular**.
*Nghịch đảo modular* của một số $a$ là một số $x$ sao cho $a \cdot x \equiv 1 \pmod m$
$x$ cũng được gọi là $a^{-1}$.
***Lưu ý:*** Ta chỉ có thể tìm được nghịch đảo modular của $a$ khi $a$ và $m$ là 2 số nguyên tố cùng nhau $\left(\gcd(a, m) = 1\right)$.
### Tìm nghịch đảo modular bằng [Euclid mở rộng](https://hackmd.io/go85krkoRnKZ8LyEMuIGNw)
Ta có: $\gcd(a, m) = 1 \Rightarrow a \cdot x + m \cdot y = 1$
mod m cho cả 2 vế (dùng công thức cộng mod bên trên $\Rightarrow$ $m \cdot y$ sẽ mất vì $m \cdot y \bmod m = 0$) $\Rightarrow a \cdot x \equiv 1 \pmod m$
```cpp!
int x, y, g;
g = extended_euclidean(a, m, x, y);
if(g == 1) {
x = (x % m + m) % m;
cout << x;
}
else
cout << "No solution";
```
### Tìm nghịch đảo modular bằng [lũy thừa nhị phân](https://hackmd.io/IsGwluMuQSuzeJ8NY0mEKw)
Theo định lý Euler, nếu $a$ và $m$ là hai số nguyên tố cùng nhau thì: $a^{\phi(m)} \equiv 1 \pmod m$ với $\phi$ là [phi hàm Euler](https://hackmd.io/3RrCoahISgOJ-3phIoXE0g#Phi-h%C3%A0m-Euler).
Nếu $m$ là số nguyên tố thì quy về [định lý nhỏ Fermat](https://vi.wikipedia.org/wiki/%C4%90%E1%BB%8Bnh_l%C3%BD_nh%E1%BB%8F_Fermat): $a^{m-1} \equiv 1 \pmod m$ (với $m$ nguyên tố thì $\phi(m) = m-1$).
Nhân cả hai vế cho $a^{-1}$ ta được:
$$a^{-1} \equiv \begin{cases} a^{m-2} &\text{với } m \text{ nguyên tố} \\ a^{\phi(m)-1} &\text{với } m \text{ không nguyên tố} \end{cases} \pmod m$$
Từ đó ta có thể dùng lũy thừa nhị phân như trên để tính.
### Tìm nghịch đảo modular cho $m$ số (chỉ áp dụng cho $m$ nguyên tố)
Ta sẽ xây dựng một mảng $inv$ để lưu lại nghịch đảo modular của các số tới $m$.
Nếu ta duyệt i từ $1$ tới $m$, sau đó tính nghịch đảo modular của từng i, độ phức tạp sẽ là $O(m \log m)$.
Tuy nhiên có một cách để tính trong $O(m)$:
Với số nguyên tố $m$ > $a$, theo Euclidean divison, tồn tại 2 số $q$ và $p$ sao cho: $m = a \cdot q + p$ với $q = \left\lfloor{m \over a}\right\rfloor$ và $p = m \bmod a$
$$m = a \cdot q + p$$
$$a \cdot q + p \equiv 0 \pmod m$$
$$a \equiv {-p \over q} \pmod m$$
$$a^{-1} \equiv {-q \over p} \pmod m$$
$$a^{-1} \equiv -q \cdot p^{-1} \pmod m$$
Có thể thấy $-q \cdot p^{-1}$ là số âm nên ta sẽ cộng thêm $m$ vào:
$$a^{-1} \equiv m - q \cdot p^{-1} \pmod m$$
Thay $q$ và $p$ như bên trên:
$$\Rightarrow a^{-1} \equiv m - \left\lfloor{m \over a}\right\rfloor \cdot (m \bmod a)^{-1} \pmod m$$
Hay: $$inv[a] \equiv m - \left\lfloor{m \over a}\right\rfloor \cdot inv[m \bmod a] \pmod m$$
Vì $m \bmod a < a$ nên ta sẽ tính được $inv[a]$ dựa vào các giá trị trước.
```cpp!
inv[0] = inv[1] = 1;
for(int i = 2; i <= MAXN; ++i) // MAXN <= mod
inv[i] = mod - (long long)(mod / i) * inv[mod % i] % mod;
```