快速乘
typedef long long ll;
ll mul(ll a, ll b, ll p) {
ll ans = (ll)((long double)a*b/p+0.5)-c*p;
return ans<0?ans+p:ans;
}
Miller-Rabin
ll qpow(ll a, ll b, ll n) {
ll ans = 1;
for (; b; b >>= 1, a = mul(a,a,n))
if (b & 1) ans = mul(ans,a,n);
return ans;
}
bool MR(ll n) {
if (n == 2) return true;
if (n < 2 || (~n & 1)) return false;
ll p = n-1; int cnt = 0;
while (~p & 1) p >>= 1, ++cnt;
for (int i = 0; i < 10; ++i) {
ll x = qpow((ll)rand()*rand()%(n-1)+1, p, n), lst = 0;
for (int j = 0; j < cnt; ++j) {
lst = x;
x = mul(x, x, n);
if (x == 1 && (lst != n-1 && lst != 1)) return false;
}
if (x != 1) return false;
}
return true;
}
Pollard-Rho
ll gcd(ll x, ll y) {
while (y != 0) {
x %= y;
swap(x, y);
}
return x;
}
ll pr(ll n) {
ll x = (ll)rand()*rand()%(n-1)+1, c = rand()%(n-1)+1, y = x, i = 1, k = 1, j = 1;
while (1) {
x = (mul(x,x,n)+c)%n;
j = mul(j,abs(y-x),n);
if ((k-i)%127 == 0) {
ll d = gcd(n, j);
if (d > 1) return d;
}
if (i++ == k) {
y = x;
k <<= 1;
}
}
}