Miller_Rabin

Miller_Rabin

Part0 前言:

Miller_Rabin是一个高效判定素数的随机算法。

其运用到的理论知识是:费马小定理 (and) 二次探测定理

Part1 费马小定理:

关于这个定理没什么好多讲的。

[若p是素数,则 a^pequiv amod p ]

Part2 二次探测定理:

[若a^2equiv 1mod p 且p是素数\ 则aequiv1 or aequiv p-1 (mod p) ]

定理的证明直接移项即可。

[ a^2equiv 1mod p\ herefore (a-1)(a+1)equiv0mod p\ herefore pmid (a-1)(a+1)\ ecause p是素数 (不是素数不能继续向下!)\ herefore pmid a-1 or pmid a+1\ 即 aequiv1 or aequiv a-1 (mod p) ]

Part3 Miller_Rabin:

假设当前需要判定的数是x。

一、那么若x为质数那么需要满足费马小定理。

​ 满足费马小定理只是x为素数的一个必要条件。如果连费马小定理都无法满足,必然不可能是素数。

二、但是上述条件并不充分。所以需要利用二次探测定理来进行再判断。

​ 由费马小定理显然有$ a^{x-1}equiv 1mod x$。

​ 又由二次探测定理有:

​ 若(2 mid x-1),则(a^{frac{x-1}{2}}equiv 1 or a^{frac{x-1}{2}}equiv x-1)

​ 若不满足二者中任意一个,则说明不是素数。

​ 若满足(a^{frac{x-1}{2}}equiv 1),则可以继续二次探测。

​ 若满足(a^{frac{x-1}{2}}equiv x-1),则无法继续探测,认定x为素数。

​ 若不满足(2 mid x-1),无法继续探测,认定x为素数。

这就是Miller_Rabin的全部过程。

事实上仍然存在很少一部分强伪素数无法被Miller_Rabin判掉。

我们可以通过多选几个数来多次判定,使这样的情况发生的概率尽可能小就好了,算法的随机就体现在这里了。

Part4 代码实现:

在代码实现过程中,若直接模拟上述流程,每一次除以2后,都需要求一个快速幂,计算次数较多。

而如果提前把所有能提出的2都先提出来,反向模拟这一过程,就只需要不断乘上自己就好了。程序会跑的更快!

IL int Miller_Rabin(int x) {
    if(x<2) return 0;
    if(x==2||x==3||x==5||x==7) return 1;
    RG int i,j,k=x-1,cnt=0,now;
    while(!(k&1)) k>>=1,++cnt;
    //先把所有的2给提出来,然后在一个一个乘上去,这样比直接做快
    for(i=1;i<=4;++i) {
        if(Pow(prm[i],x-1,x)!=1) return 0; //费马小定理
        now=Pow(prm[i],k,x);
        if(now==1||now==x-1) continue;
        now=now*now%x;
        for(j=1;j<=cnt;++j,now=now*now%x)
            if(now==x-1) break;
        if(j>cnt) return 0;
    }
    return 1;
}
原文地址:https://www.cnblogs.com/Bhllx/p/11561439.html