Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Tìm căn bậc hai modulo p (Thuật toán Shanks-Tonelli) trong C++


Trong bài toán này, chúng ta được cho hai giá trị n và một số nguyên tố p. Nhiệm vụ của chúng ta là tìm căn bậc hai dưới modulo p.

Hãy xem ví dụ sau để hiểu bài toán:

Input : n = 4, p = 11 Output : 9

Phương pháp giải

Ở đây, ta sẽ sử dụng Thuật toán Tonelli-Shanks.

Thuật toán Tonelli-Shanks được dùng trong số học modulo để giải giá trị x trong đồng dư dạng x² = n (mod p).

Thuật toán tìm căn bậc hai modulo bằng thuật toán Shanks-Tonelli:

Bước 1 − Tìm giá trị $(n^{((p-1)/2)})(mod\:p)$, nếu giá trị là p-1, thì căn bậc hai modulo không tồn tại.

Bước 2 − Sau đó, ta dùng giá trị p-1 dạng (s * 2e). Trong đó s là số lẻ dương và e là số dương.

Bước 3 − Tính giá trị q^((p-1)/2)(mod p) = -1

Bước 4 − Dùng vòng lặp cho m lớn hơn 0 và cập nhật giá trị x,

Tìm m sao cho b^(2^m) - 1(mod p) với 0 <= m <= r-1.

Nếu M là 0, trả về x, ngược lại cập nhật giá trị:

x = x * (g^(2 ^ (r - m - 1)) b = b * (g^(2 ^ (r - m)) g = (g^(2 ^ (r - m - 1)) r = m

Ví dụ

Chương trình minh họa cho giải pháp,

#include <iostream> #include <math.h> using namespace std; int powerMod(int base, int exponent, int modulus) {    int result = 1;    base = base % modulus;    while (exponent > 0) {       if (exponent % 2 == 1)       result = (result * base)% modulus;       exponent = exponent >> 1;       base = (base * base) % modulus;    }    return result; } int gcd(int a, int b) {    if (b == 0)    return a;    else    return gcd(b, a % b); } int orderValues(int p, int b) {    if (gcd(p, b) != 1) {       return -1;    }    int k = 3;    while (1) {       if (powerMod(b, k, p) == 1)       return k;       k++;    } } int findx2e(int x, int& e) {    e = 0;    while (x % 2 == 0) {       x /= 2;       e++;    }    return x; } int calcSquareRoot(int n, int p) {    if (gcd(n, p) != 1) {       return -1;    }    if (powerMod(n, (p - 1) / 2, p) == (p - 1)) {       return -1;    }    int s, e;    s = findx2e(p - 1, e);    int q;    for (q = 2; ; q++) {       if (powerMod(q, (p - 1) / 2, p) == (p - 1))       break;    }    int x = powerMod(n, (s + 1) / 2, p);    int b = powerMod(n, s, p);    int g = powerMod(q, s, p);    int r = e;    while (1) {       int m;       for (m = 0; m < r; m++) {          if (orderValues(p, b) == -1)          return -1;          if (orderValues(p, b) == pow(2, m))          break;       }       if (m == 0)       return x;       x = (x * powerMod(g, pow(2, r - m - 1), p)) % p;       g = powerMod(g, pow(2, r - m), p);       b = (b * g) % p;       if (b == 1)       return x;       r = m;    } } int main() {    int n = 3;    int p = 13;    int sqrtVal = calcSquareRoot(n, p);    if (sqrtVal == -1)       cout<<"Modular square root is not exist";    else cout<<"Modular square root of the number is "<<sqrtVal; }

Kết quả

Modular square root of the number is 9