Miller-Rabin 素数判定

费马小定理:

a p 1 1 m o d ( p ) a^{p-1}\equiv 1 mod (p) (p为质素)

二次探测原理

x 2 1 m o d ( p ) x^2\equiv 1mod(p) (p为质素)
x = 1 x = p 1 x=1 || x=p-1

对于二次的证明

x 2 1 m o d ( p ) x 2 1 0 m o d ( p ) x^2\equiv 1 mod (p) \Rightarrow x^2-1 \equiv 0 mod(p)
( x 1 ) × ( x + 1 ) m o d ( p ) \Rightarrow (x-1)\times(x+1)\equiv mod (p)
x 1 = 0 x = 1 \Rightarrow x-1=0 \Rightarrow x=1
||   x + 1 = 0 x = 1 = 1 + p = p 1 x+1=0\Rightarrow x=-1=-1+p=p-1

就是根据以上这两个定理有了素数探测,但是这个算法不保证结论一定正确,每一次的出错率大概是 1 / 4 1/4 ,所以说需要多次测试以提高正确性。
过程参看这篇博客: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;
}
发布了70 篇原创文章 · 获赞 5 · 访问量 7177

猜你喜欢

转载自blog.csdn.net/xiaonanxinyi/article/details/98886029
今日推荐