费马小定理:
(p为质素)
二次探测原理
(p为质素)
对于二次的证明
||
就是根据以上这两个定理有了素数探测,但是这个算法不保证结论一定正确,每一次的出错率大概是
,所以说需要多次测试以提高正确性。
过程参看这篇博客:Miller-Rabin素性测试算法详解
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int times = 20;
ll Random(ll n){
return ((double)rand() / RAND_MAX * n + 0.5);
}
ll mul(ll a, ll b, ll mod) {
ll ans = 0;
while (b){
if (b & 1)ans = (ans + a) % mod;
b >>= 1;
a = a * 2 % mod;
}
return ans;
}
ll powmod(ll a, ll b, ll mod){
ll ans = 1;
while (b){
if (b & 1)ans = mul(ans, a, mod);
b >>= 1;
a = mul(a, a, mod);
}
return ans;
}
bool witness(ll a, ll n){
ll tem = n - 1;
int j = 0;
while (tem % 2 == 0){
tem /= 2;
j++;
}
ll x = powmod(a, tem, n);
if (x == 1 || x == n - 1) return true;
while (j--){
x = mul(x, x, n);
if (x == n - 1) return true;
}
return false;
}
bool miller_rabin(ll n){
if (n == 2)
return true;
if (n < 2 || n % 2 == 0)
return false;
for (int i = 1; i <= times; i++){
ll a = Random(n - 2) + 1;
if (!witness(a, n))
return false;
}
return true;
}
bool isprime(ll x) {
for (ll i = 2; i*i <= x; i++)if (x%i == 0)return false;
return true;
}
int main()
{
ll x=1e17 +23125;
cout << miller_rabin(x) << endl;
cout << isprime(x) << endl;
return 0;
}