素性测试
Miller Rabin
cpp
bool miller_rabin(i64 n) {
if (!is_prime_small(n))
return false;
i64 a = n - 1;
a /= a & -a;
for (int p : {2, 3, 5, 7, 11, 13, 17, 19, 23}) {
if (n <= p)
return true;
i64 t = a, v = qpow64(p, t, n);
while (t != n - 1 && v != 1 && v != n - 1)
v = i128(v) * v % n, t *= 2;
if (v != n - 1 && t % 2 == 0)
return false;
}
return true;
}
cpp
using i128 = __int128_t;
i64 qpow64(i64 a, i64 n, i64 m) {
i64 ret = 1 % m;
for (; n; n /= 2) {
if (n & 1)
ret = i128(a) * ret % m;
a = i128(a) * a % m;
}
return ret;
}
bool is_prime_small(i64 n) {
if (n < 64)
return (0x28208a20a08a28ac >> n) & 1;
if ((0xdf75d77d >> (n % 30)) & 1)
return false;
if (n % 7 == 0 || n % 11 == 0)
return false;
return true;
}
bool miller_rabin(i64 n) {
if (!is_prime_small(n))
return false;
i64 a = n - 1;
a /= a & -a;
for (int p : {2, 3, 5, 7, 11, 13, 17, 19, 23}) {
if (n <= p)
return true;
i64 t = a, v = qpow64(p, t, n);
while (t != n - 1 && v != 1 && v != n - 1)
v = i128(v) * v % n, t *= 2;
if (v != n - 1 && t % 2 == 0)
return false;
}
return true;
}