【数论】Miller_Rabin

Miller_Rabin素数测试

    Miller_Rabin判断单个素数的方法运用了费马小定理,可以说非常之快了。

    Miller_Rabin曾经被称作“黑科技”,但是根据费马小定理其实完全可以自己写出来大半。

 

    其算法的运行过程如下:

    (1)对于奇数M,使得N=(2^r)*M+1

    (2)选取随机数使得A<N

    (3)对于任意i(i<r),若(A^(2^i)) Mod N=N - 1,则N为素数

    (4)或者,若(A^M) Mod N=1,则N通过随机数A的测试

    若对素数N进行T次测试,那么失误率为1/4^T,我们可以进一步提高其效率,如省去步骤3

   

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<time.h>
#include<cstdlib>
#include<cmath>
using namespace std;
long long exp(long long a,long long m,long long n){//快速幂
	if(m==0) return 1;
	if(m==1) return (a%n);
	long long w=exp(a,m/2,n);
	w=w*w%n;
	if(m&1) w=w*a%n;
	return w%n;
}
bool Witness(long long a,long long n)
{
    long long m=n-1;//满足原先条件
    int j=0;
    while(!(m&1)){
        j++;
        m>>=1;
    }
    long long x=exp(a,m,n);
    if(x==1||x==n-1) return false;
    while(j--){
        x=x*x%n;
        if(x==n-1) return false;
    }
    return true;
}
bool Miller_Rabin(long long n){
	if(n==2) return true;
	if(n&1==0) return false;
	for(int i=1;i<=10;i++){
		long long a=rand()%(n-2)+2;//一定为a<N
		if(Witness(a,n)) return false;
	}
	return true;
}
bool prime(long long N){
	long long k=sqrt(N);
	for(int i=2;i<=k;i++) if(N%i==0) return false;
	return true;
}
int main(){
    srand(time(NULL));
    for(long long i=3;i<=10000000;i++)
    if(Miller_Rabin(i)!=prime(i)) cout<<i<<endl;
}

  

posted @ 2016-11-26 22:50  wxjor  阅读(245)  评论(0编辑  收藏  举报