Miller-Rabin kiểm tra số nguyên tố trong và Pollard's Rho phân tích thừa số nguyên tố trong — hiệu quả cho .
Miller-Rabin
Kiểm tra có nguyên tố không bằng cách kiểm tra điều kiện Fermat mạnh với một số cơ sở .
Nguyên lý: Nếu nguyên tố và , thì với mọi nguyên tố cùng nhau với :
- , hoặc
- với một .
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
ll mulmod(ll a, ll b, ll m) {
return (__int128)a * b % m;
}
ll power(ll a, ll b, ll m) {
ll res = 1; a %= m;
for (; b > 0; b >>= 1) {
if (b & 1) res = mulmod(res, a, m);
a = mulmod(a, a, m);
}
return res;
}
bool miller_rabin(ll n, ll a) {
if (n % a == 0) return n == a;
ll d = n - 1; int r = 0;
while (d % 2 == 0) { d /= 2; r++; }
ll x = power(a, d, n);
if (x == 1 || x == n-1) return true;
for (int i = 0; i < r-1; i++) {
x = mulmod(x, x, n);
if (x == n-1) return true;
}
return false;
}
bool is_prime(ll n) {
if (n < 2) return false;
if (n == 2 || n == 3 || n == 5 || n == 7) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
// Các cơ sở này đủ cho n < 3.3 * 10^24 (deterministic)
for (ll a : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37})
if (!miller_rabin(n, a)) return false;
return true;
}
Độ phức tạp: — nhanh hơn rất nhiều với .
Pollard's Rho
Tìm một ước nguyên tố của trong bằng phương pháp cycle detection của Floyd.
ll pollard_rho(ll n) {
if (n % 2 == 0) return 2;
ll x = rand() % (n-2) + 2;
ll y = x;
ll c = rand() % (n-1) + 1;
ll d = 1;
while (d == 1) {
x = (mulmod(x, x, n) + c) % n;
y = (mulmod(y, y, n) + c) % n;
y = (mulmod(y, y, n) + c) % n;
d = __gcd(abs(x - y), n);
}
return d;
}
// Phiên bản Brent (nhanh hơn)
ll brent(ll n) {
if (n % 2 == 0) return 2;
ll y = rand() % (n-1) + 1, c = rand() % (n-1) + 1, m = rand() % (n-1) + 1;
ll g = 1, q = 1, r = 1, ys, x;
while (g == 1) {
x = y;
for (ll i = 0; i < r; i++) y = (mulmod(y, y, n) + c) % n;
ll k = 0;
while (k < r && g == 1) {
ys = y;
for (ll i = 0; i < min(m, r-k); i++) {
y = (mulmod(y, y, n) + c) % n;
q = mulmod(q, abs(x-y), n);
}
g = __gcd(q, n);
k += m;
}
r <<= 1;
}
if (g == n) {
while (true) {
ys = (mulmod(ys, ys, n) + c) % n;
g = __gcd(abs(x - ys), n);
if (g > 1) break;
}
}
return g;
}
Phân tích thừa số nguyên tố hoàn chỉnh
map<ll, int> factorize(ll n) {
map<ll, int> factors;
function<void(ll)> factor = [&](ll n) {
if (n == 1) return;
if (is_prime(n)) { factors[n]++; return; }
ll d = n;
while (d == n) d = brent(n);
factor(d); factor(n / d);
};
factor(n);
return factors;
}
int main() {
ll n; cin >> n;
auto f = factorize(n);
for (auto [p, e] : f)
cout << p << "^" << e << " ";
}
So sánh với sàng nguyên tố
| Sàng Eratosthenes | Miller-Rabin | Pollard's Rho | |
|---|---|---|---|
| Kiểm tra nguyên tố | sau sàng | — | |
| Phân tích | — | ||
| Giới hạn | (sàng) |
Khi nào dùng Miller-Rabin / Pollard's Rho?
- : quá lớn cho sàng hoặc .
- Kiểm tra nhiều số nguyên tố lớn nhanh.
- Phân tích thừa số nguyên tố của số lớn (tính , số ước,...).
Bình luận