## Nghịch đảo modulo ### Định nghĩa Ở chương trình Toán phổ thông, nghịch đảo của một số nguyên $a$ có kí hiệu là $a^{-1}$ hay viết một cách dễ hiểu hơn là $\frac{1}{a}$, thỏa mãn: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$a \times a^{-1}$ = 1 Đối với nghịch đảo Modulo, ta cũng có khái niệm tương tự: Nghịch đảo modulo **$M$** của một số $a$ (kí hiệu là $a^{-1}$) là số nguyên thỏa mãn điều kiện: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $a \times a^{-1} \equiv 1 \pmod{M}$ Tuy vậy, $a^{-1}$ hay nghịch đảo modulo $M$ của $a$ không phải lúc nào cũng tồn tại mà chỉ xuất hiện khi và chỉ khi thỏa mãn được điều kiện: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$GCD(a, M) = 1$ Và để tìm được nghịch đảo modulo M của số $a$ bất kì, ta có thể sử dụng hai phương pháp sau: Giải thuật $Euclid$ mở rộng hoặc dựa trên định lý $Fermat$ nhỏ. ### Giải thuật $Euclid$ mở rộng Theo cơ sở lý thuyết của giải thuật $Euclid$ mở rộng thì sẽ luôn luôn tồn tại các số nguyên $x, y$ thỏa mãn: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$ax + by = d$&nbsp;&nbsp;&nbsp;$\mid$&nbsp;&nbsp; $d = GCD(a, b)$&nbsp;&nbsp;&nbsp;$\forall$&nbsp;&nbsp; $a, b$ $\in$ $N$ Giải thuật này được sử dụng phổ biến nhằm để tìm ra được cặp số nguyên $(x, y)$&nbsp;&nbsp;$\in$ $N$ thỏa mãn phương trình trên và còn để dùng để tính nghịch đảo modulo. Áp dụng giải thuật này lên định nghĩa đã được phát biểu ở phần trên, ta được: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$GCD(a, M) = 1$ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$\Rightarrow$ $a \times x + M \times y = 1$ & $M \times y$ chia hết cho $M$ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$\Rightarrow$ $a \times x \equiv 1 \pmod{M}$ Từ đây, ta có thể kết luận $x$ chính là $a^{-1}$. Tuy vậy, trong giải thuật $Euclid$ mở rộng, $x$ hay $a^{-1}$ có thể mang giá trị âm, nên ta sẽ cần điều chỉnh một chút để luôn được giá trị $a^{-1}$ luôn không âm. Code: ```cpp= #include <bits/stdio.h> using namespace std; long long d; // d là UCLN của a, M long long modulo_inverse(long long a, long long M) { extended_euclid(a, M); // a và M không nguyên tố cùng nhau, không tồn tại nghịch đảo modulo M của a. if (d != 1) return -1; // Do x có thể âm, ta làm dương nó. return (x % M + M) % M; } ``` ### Định lý $Fermat$ nhỏ Dựa vào định lý $Fermat$ nhỏ, ta có được: Nếu $M$ là số nguyên tố và $a$ không chia hết cho $M$ thì $a^{M - 1} - 1$ sẽ chia hết cho $M$: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$a^{M-1}\equiv 1 \ (\text{mod} \ M)$ hay nói cách khác: $a\times a^{M-2} \equiv 1 \ (\text{mod} \ M)$ Điều này cũng có nghĩa là nếu $M$ là số nguyên tố và $a$ không chia hết cho $M$ thì $a^{M - 2}$ là nghịch đảo modulo $M$ của $a$, cũng tương tự với $a^{M - 2}$ % $M$ là nghịch đảo modulo của $a$. ```cpp= #include <bits/stdio.h> using namespace std; long long power_mod(long long a, long long b, long long M) // Tính a^b % M { if (b == 0) return 1; if (b == 1) return a; long long half = power_mod(a, b / 2, M) % M; if (b % 2 == 0) return (half * half) % M; else return (((half * half) % M) * a) % M; } long long modulo_inverse(int a, int M){ return power_mod(a, M – 2, M); } ``` ### Áp dụng #### Bài toán : Tính $\frac{a}{b}$ % $c$ Để tính được phép tính ở trên, ta cần có một chút biến đổi nhỏ để đưa phép chia trên thành 1 phép nhân với mục đích lợi dụng nghịch đảo modulo tính được số dư: - Tách $\frac{a}{b} \ \% \ c$ = $(a \times \frac{1}{b}) \ \% \ c$ = $(a \times b^{-1}) \ \% \ c$ với $b^{-1}$ là nghịch đảo modulo $c$ của $b$. - Sau đó, ta sẽ áp dụng tính chất phân phối của phép nhân lên phép đồng dư thức. Ta sẽ được một phép nhân với nghịch đảo modulo. * **Lưu ý**: Tùy vào giá trị của $c$ mà ta chọn cách tính nghịch đảo modulo hợp lí, phù hợp. ```cpp= long long modulo_divide(long long a, long long b, long long c){ long long inverse = modulo_inverse(b, c); return (a % c * inverse) % c; } ```