Miller_Rabin测试法

版权声明:个人笔记,仅供复习 https://blog.csdn.net/weixin_41162823/article/details/85236692

简介:Miller_Rabin法是一种简便的素数测试方法,一般用于测试大数是否为素数

Miller_Rabin测试原理:如果n是素数,且与a互质,则a^{n-1}\equiv 1(mod n) 。(1)

证明:请参考费马小定理证明方法。

思路:依据上述原理,我们可以不断选取与 n 互质的 a ,如果上式(1)都成立的话,那么n可能是一个素数,否则一定不是一个素数。如此一来只要a取得够多,就可以保证结果的准确度。一般在32位内的任一个整数n,如果其通过以2、7、61为底的Miller_Rabin测试,那其一定是素数,反之则一定不是。

优化:通过(1)式,只能说大概率验证素性,但是仅仅如此是不够的,为了减少误判的可能,同时大大减少计算量,可以通过如下结论进行优化:

定理:如果a^{2}\equiv 1(mod n),则必有a\equiv 1(mod n)a \equiv n-1(mod n)

如果有一个大于2的质数 n ,令 n - 1 = 2^s * d,其中d为奇数,根据费马小定理,如果a不能被素数n整除,那么a^{n-1}\equiv 1(mod n)。于是可以得出:,a^{d}\equiv 1或者a^{2}\equiv 1(mod n)a^{2r*d}\equiv n-1(mod n),(0<= r < s)。

于是只要找到一个a,满足a^{2}\not\equiv1(mod n)或者存在一个自然数r(0 <= r < s),使得a^{2r*d}\not\equiv n-1(mod n),就可以说明n一定不是素数,反之则有可能是素数。

模板:

#include<cstdio>
typedef long long ll;

ll qpow(ll a,ll b,ll m){	//快速幂算法 
	ll res = 1;
	while(b){
		if(b&1)	res = res*a%m;
		a = a*a%m;
		b >>= 1;
	}
	return res%m;
}

bool Miller(ll x,ll n){		//Miller_Rabin测试 
	ll b = n-1;
	while(!(b&1)) b >>= 1;
	x = qpow(x,b,n);		//此时b为没有因子2的奇数 
	while(b < n-1 && x != 1 && x != n-1)
		x = (x*x)%n,b <<= 1; 
	return x == n-1 || b&1 == 1;
	//当x=n-1,或b为奇数时返回true; 
}
bool isPrime(ll n){
	if(n == 2 || n == 7 || n == 61)	return true;
	if(n == 1 || !(n&1)) return false;
	return Miller(2,n)&&Miller(7,n)&&Miller(61,n);
}
int main(){
	ll n;
	scanf("%lld",&n);
	if(isPrime(n))	puts("Yes");
	else puts("No");
} 

猜你喜欢

转载自blog.csdn.net/weixin_41162823/article/details/85236692