Miller-Rabin素数测试

来源:互联网 发布:js 调用方法加new 编辑:程序博客网 时间:2024/05/29 16:56

素数测试

素数测试是数论中常见的算法,所以对它的优化也是很有必要的,其中Miller_Rabin素数测试是一种很有效的算法,优化,在探究该算法之前,我们先来探究一下素数测试的前生今世

素数的朴素筛法

从素数的定义方法,我们可以知道,素数P不会被2-(P-1)整除,我们即可以用这种性质来筛去所有合数,而通过该测试的即为素数。
具体代码实现如下:

Bool IsPrime(int num){    for(int i = 2 ; i <= num-1 ; i++){        if(num % i !=0){            return false;        }    }       Return true;        }

该算法的时间复杂度为O(n)效率较低,我们可以采取一下优化

  • 优化1:已知当对任意的x>P为P的因数,都有与之对应的y<P,使得xy=P,所以一旦y能够筛掉P,则x亦能筛掉P,所以我们只需要判断PP
  • 优化2: 我们可以预处理一些小素数,比如判断出2是素数,则2的倍数就是合数,则预先处理2,则不需要用(2n)来筛P,则判断次数可以降低至一半
    代码实现如下
Bool IsPrime(int num){    if(num == 2)return true;    if(num % 2 ==0)return false;    int to = sqrt ( num );    for(int i = 2 ; i <= to ; i+=2){        if(num % i !=0){            return false;        }    }       Return true;        }

如此优化后,该算法的时间复杂度降为O(n2),可以在1s以内处理出Long Long范围内的任意一个数字.

费马素数筛法

费马小定理证明了AP11(mod P),如果不知道的可以点这里依次性质我们可以利用费马小定理的逆定理来测试素数.
即判断kP1%P是否等于1(k为任意正整数).
虽然费马小定理可以被严格证明,但它的反定理不一定成立,其中最小的一个反例是341,对于这中非素数,而能通过费马测试的数,我们称之为伪素数.而且数论学家们已经证明这样的伪素数有无穷多个.但无论如何,我们可以知道,虽然通过费马测试的不一定是素数,但素数是一定可以通过费马测试,我们可以尽可能增多测试次数来增加测试准确度.
当我们以2为底测试时,代码如下:

int Fpow(int k,int p,int mod){    int ans = 1;    while( p ){        if(p & 1)(ans *= k) %= mod;        (k *= k) %= mod;        p >>= 1    }    return ans;}Bool IsPrime(int num){    if(num == 2)return true;    if( Fpow(2,num-1,num) == 1)return true;    return false;}

依上所述,341是第一个可以卡掉这个算法的伪素数.但我们以相同格式加入3时,即可筛掉341,即可以在1000以内没有判断错误,当我们使用2,3,5,7时,即可做到在20000以内没有错误判断,该算法的核心是快速幂,故时间复杂度较低,为O(4log2n)。但随着我们的范围扩大,所需要的用于判断的素数就越多,并且有一种强伪素数被发现,能够通过比它小的所有数的费马测试。则这种算法的弊端就暴露出来,所以这种算法只在人品极好时才推荐使用.
因此我们就有两位伟大的数论学家Miller,Rabin发明了Miller_Rabin算法

Miller_Rabin素数测试

然而伪素数,也是有弱点的,在证明威尔逊定理时,我们已经发现,对于任意一个质数P,都有所有小于P的数x都有与之配对的数y使得xy % p = 1

原创粉丝点击