【数论】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; }
你——悟到了么?