【作用】
一般素数判定方法有试除法和Miller-Rabin。试除法枚举2-√n,时间复杂度为O(√n) , 一旦n特别大,就不适合用试除法进行判定。
这时候我们可以对其进行 Miller-Rabin 素数测试,可以大概率测出其是否为素数。
【两个基础理论】
(1):费马小定理:当p为质数时,有ap-1≡1(mod p).注意逆命题是假命题,比如卡迈克尔(Carmichael)数。
对于合数满足费马小定理的数叫伪素数,
(2):二次测探:如果p是一个素数,0<x<p,则方程x2≡1(mod p)的解为x = 1 或 x = p - 1.
(1)对于一些常见的素数和非素数 可以直接判断。
(2)设要测试的数为 x,我们取一个较小的质数 a,设 s,t,满足 2s * t = x - 1(其中 t 是奇数)。
(3)我们先算出 a^t,然后不断地平方并且进行二次探测(进行 s 次)。
(4)最后我们根据费马小定律,如果最后不满足费马小定理 ,则说明 x 为合数。
(5)多次取不同的 a 进行 Miller-Rabin 素数测试,这样可以使正确性更高
https://blog.csdn.net/forever_dreams/article/details/82314237
https://www.cnblogs.com/Antigonae/p/10226580.html
int quickmul(int a , int b , int m){ return ((a * b - (ll)(long double)(a/m*b) * m)+m)%m ; } int quickpow(int a , int b , int m){ int ans = 1 ; while(b){ if(b&1) ans = quickmul(ans , a , m) ; b >>= 1 ; a = quickmul(a , a , m); } return ans ; } bool Miller_Rabin(int n){ if(n == 46856248255981ll || n < 2) return false; if(n == 2 || n == 3 || n == 7 || n == 61 || n == 24251) return true; if(!(n&1) || !(n%3) || !(n%61) || !(n%24251)) return false; int m = n - 1 , k = 0 ; while(!(m&1)) k++ , m>>=1 ;// 分解2^s * t = n - 1 rep(i , 1 , 20){ int a = rand() % (n - 1) + 1 , x = quickpow(a , m , n) , y; rep(j , 1 , k){ y = quickmul(x , x , n); if(y == 1 && x != 1 && x != n - 1) return false;//二次测探 x = y ; } if(y != 1) return false;//费马小定理 } return true; } void solve(){ int x ; cin >> x ; if(Miller_Rabin(x)) cout << "Yes" << endl; else cout << "No" << endl; }