Cách tính modulo
Đồng dư thức là phép toán lấy số dư của số này khi chia cho số khác, kí hiệu là %\%%. Ví dụ: 5%2=15 \% 2=15%2=1, khi đó có thể viết là 5≡15 \equiv 15≡1 (mod(mod(mod 2)2)2). Show Phép đồng dư thức có tính chất phân phối đối với phép cộng, phép nhân và phép trừ, cụ thể như sau:
Riêng đối với phép chia, chúng ta không có tính chất phân phối, mà phải sử dụng một lí thuyết là Nghịch đảo modulo. 2. Nghịch đảo modulo của một sốNhư chúng ta đều biết ở chương trình Toán phổ thông, nghịch đảo của một số nguyên aaa (kí hiệu a−1a^{-1}a−1) là số thỏa mãn: a.a−1=1a.a^{-1}=1a.a−1=1. Đối với nghịch đảo modulo, ta cũng có khái niệm tương tự, nhưng là xét trên tập số dư khi chia cho MMM. Nghịch đảo modulo MMM của một số aaa (cũng kí hiệu a−1a^{-1}a−1) là số nguyên thỏa mãn: a.a−1≡1 (moda.a^{-1}\equiv1\ (moda.a−1≡1 (mod M)M)M) (Nói cách khác, a−1a^{-1}a−1 chính là 1a\frac{1}{a}a1 %\%% M)M)M). Lấy ví dụ, nếu ta chọn M=109+7,a=2M={10}^9+7, a=2M=109+7,a=2 thì a−1=500000004a^{-1}=500000004a−1=500000004. Không phải lúc nào cũng tồn tại a−1a^{-1}a−1. Chỉ khi GCD(a,M)=1\text{GCD}(a, M)=1GCD(a,M)=1 thì mới tồn tại a−1a^{-1}a−1 là nghịch đảo modulo MMM của aaa. Để tính nghịch đảo modulo của một số, ta có thể sử dụng hai giải thuật: Giải thuật Euclid mở rộng hoặc dựa trên định lý Fermat nhỏ (áp dụng giải thuật chia để trị tính ab % ca^b \ \% \ cab % c). 2.1. Sử dụng giải thuật Euclid mở rộngNhư đã trình bày ở trên, theo giải thuật Euclid mở rộng, nếu GCD(a,M)=1GCD\left(a,M\right)=1GCD(a,M)=1, ta luôn tìm được xxx và yyy thỏa mãn: a.x+M.y=1a.x+M.y=1a.x+M.y=1. Mà M.yM.yM.y chia hết cho MMM, do đó phương trình trở thành: a.x≡1(mod M)a.x \equiv 1 (\text{mod} \ M) a.x≡1(mod M) Từ đây suy ra xxx chính là a−1a^{-1}a−1. Tuy nhiên trong giải thuật Euclid mở rộng, xxx có thể mang giá trị âm, nên ta sẽ điều chỉnh một chút để tính được giá trị a−1a^{-1}a−1 luôn không âm. long long x; long long modulo_inverse(long long a, long long M) { long long gcd = extended_euclid(a, M); if (gcd != 1) return -1; return (x % M + M) % M; }2.2. Tính nghịch đảo modulo bằng định lý Fermat nhỏTheo định lý Fermat nhỏ, ta có: Nếu MMM là số nguyên tố và aaa không chia hết cho MMM thì: aM−1≡1 (mod M)a^{M-1} \equiv 1 \ (\text{mod} \ M) aM−1≡1 (mod M) hay nói cách khác: a×aM−2≡1 (mod M)a \times a^{M-2} \equiv 1 \ (\text{mod} \ M) a×aM−2≡1 (mod M) Điều này tương đương với việc nếu MMM là số nguyên tố và aaa không chia hết cho MMM thì aM−2a^{M-2}aM−2 chính là nghịch đảo modulo MMM của aaa, cũng tương đương với aM−2a^{M-2}aM−2 %\%% MMM là nghịch đảo modulo MMM của aaa. 3. Áp dụng nghịch đảo modulo để tính ab % c\frac{a}{b} \ \% \ cba % cMình đã đề cập ở mục 111, phép chia không có tính chất phân phối đối với phép đồng dư thức giống như các phép cộng, trừ và nhân. Để tính ab % c,\frac{a}{b} \ \% \ c,ba % c, ta làm như sau:
Cài đặt: 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; }4. Bậc lũy thừa theo modulo NNN (Multiplicative Order)Xét hai số nguyên aaa và NNN nguyên tố cùng nhau, bậc lũy thừa của aaa theo modulo NNN là số nguyên dương KKK nhỏ nhất thỏa mãn: aK≡1 (mod N)a^K \equiv 1 \text{ } (mod \text{ } N)aK≡1 (mod N), kí hiệu là ordN(a)ord_N(a)ordN(a). Theo định lý Euler, vì aaa và NNN là hai số nguyên tố cùng nhau nên aϕ(N)≡1 (mod N),a^{\phi(N)} \equiv 1 \ (\text{mod} \ N),aϕ(N)≡1 (mod N), với ϕ(N)\phi(N)ϕ(N) là số lượng số nguyên dương không vượt quá NNN và nguyên tố cùng nhau với NNN. Mà ϕ(N)≤N\phi(N) \le Nϕ(N)≤N, do đó ordN(a)≤Nord_N(a) \le NordN(a)≤N, vậy để tìm ordN(a)ord_N(a)ordN(a) chỉ cần duyệt một vòng lặp từ 111 tới NNN với độ phức tạp O(N−1)O(N - 1)O(N−1). int find_m_order(int a, int N) { int mul = 1; for (int i = 1; i <= N; ++i) { mul = (mul * a) % N; if (mul == 1) return i; } }5. Tiêu chuẩn Euler (Euler's Criterion)Đầu tiên, ta làm quen với khái niệm Thặng dư bậc hai: Một số nguyên qqq được gọi là thặng dư bậc hai theo modulo NNN nếu như nó đồng dư với một số chính phương theo modulo N,N,N, nghĩa là tồn tại một số nguyên xxx sao cho x2≡q (mod N)x^2 \equiv q \ (\text{mod} \ N)x2≡q (mod N). Trong lý thuyết số, tiêu chuẩn Euler là một công thức dùng để xác định xem một số nguyên có phải là một thặng dư bậc hai theo modulo PPP (với PPP là một số nguyên tố) hay không. Theo đó, xét hai số nguyên aaa và PPP nguyên tố cùng nhau, trong đó PPP là một số nguyên tố lẻ. Ta có công thức sau: Đối với trường hợp P=2,P=2,P=2, mọi số nguyên đều là thặng dư bậc hai theo modulo PPP. Ví dụ, xét P=7P = 7P=7, ta có a=2a = 2a=2 là thặng dư bậc hai của 7,7,7, vì tồn tại hai số nguyên x=3x = 3x=3 và x=4x = 4x=4 thỏa mãn a≡x2 (mod P)a \equiv x^2 \text{ } (mod \text{ } P)a≡x2 (mod P). long long power_mod(long long a, long long b, long long P) { if (b == 0) return 1; if (b == 1) return a; long long half = power_mod(a, b / 2, P) % P; if (b % 2 == 0) return (half * half) % P; else return (((half * half) % P) * (a % P)) % P; } bool check_quadratic_residue(long long N, long long P) { if (P == 2) return true; else return (power_mod(N, (P - 1) / 2, P) == 1); }Trong trường hợp NNN và PPP cùng có dạng 4i+3 (i>0)4i + 3 \ (i > 0)4i+3 (i>0), thì giá trị xxx thỏa mãn x2≡N (mod P)x^2 \equiv N \ (\text{mod} \ P)x2≡N (mod P) (nếu tồn tại) chỉ có thể là: x=± NP+14x=\pm \text{ }N^{\frac{P + 1}{4}}x=± N4P+1. Dựa vào nhận xét này ta có thể tính nhanh ra giá trị xxx. Chứng minh nhận xét như sau:
NP+12 % P=N % P (1)N^{\frac{P + 1}{2}} \ \% \ P = N \ \% \ P \ (1) N2P+1 % P=N % P (1)
Cài đặt: int find_quadratic_residue(int N, int P) { if (P % 4 != 3 || N % 4 != 3) return -1; int x = power_mod(N, (P + 1) / 2, P); if ((x * x) % P == N % P) return x; x = P - x; if ((x * x) % P == N % P) return x; return -1; } |