Miller Rabin算法详解

何为Miller Rabin算法

首先看一下度娘的解释(若是你懒得读直接跳过就能够反正也没啥乱用:joy:)算法

Miller-Rabin算法是目前主流的基于几率的素数测试算法,在构建密码安全体系中占有重要的地位。经过比较各类素数测试算法和对Miller-Rabin算法进行的仔细研究,证实在计算机中构建密码安全体系时, Miller-Rabin算法是完成素数测试的最佳选择。经过对Miller-Rabin 算 法底层运算的优化,能够取得较以往实现更好的性能。[1]  随着信息技术的发展、网络的普及和电子商务的开展, 信息安全逐步显示出了其重要性。信息的泄密、伪造、篡改 等问题会给信息的合法拥有者带来重大的损失。在计算机中构建密码安全体系能够提供4种最基本的保护信息安全的服 务:保密性、数据完整性、鉴别、抗抵赖性,从而能够很大 程度上保护用户的数据安全。在密码安全体系中,公开密钥 算法在密钥交换、密钥管理、身份认证等问题的处理上极其有效,所以在整个体系中占有重要的地位。目前的公开密钥 算法大部分基于大整数分解、有限域上的离散对数问题和椭 圆曲线上的离散对数问题,这些数学难题的构建大部分都需 要生成一种超大的素数,尤为在经典的RSA算法中,生成的素数的质量对系统的安全性有很大的影响。目前大素数的生 成,尤为是随机大素数的生成主要是使用素数测试算法,本 文主要针对目前主流的Miller-Rabin 算法进行全面系统的分析 和研究,并对其实现进行了优化安全

说白了Miller Rabin算法在信息学奥赛中的应用就一句话:网络

判断一个数是不是素数性能

定理

Miller Rabin算法的依据是费马小定理:测试

$$a^{p-1}\equiv 1 \pmod P$$优化

证实:ui

性质1:$p-1$个整数$a,2a,3a,...(p-1)a$中没有一个是$p$的倍数 spa

性质2:$a,2a,3a,...(p-1)a$中没有任何两个同余与模$p$的code

因此$a,2a,3a,...(p-1)a$对模$p$的同余既不为零,也没有两个同余相同blog

所以,这$p-1$个数模$p$的同余必定是$a,2a,3a,...(p-1)a$的某一种排列

即$a*2a*3a*...*(p-1)a \equiv {1*2*3*...*(p-1)} \pmod p$

化简为

$a^{p-1}*(p-1)! \equiv {p-1}! \pmod p$

根据威尔逊定理可知$(p-1)!$与$p$互质,因此同时约去$(p-1)!$

即获得$a^{p-1}\equiv 1 \pmod P$

 

那么是否是当一个数$p$知足任意$a$使得$a^{p-1}\equiv 1 \pmod P$成立的时候它就是素数呢?

在费马小定理被证实后的很长一段时间里,人们都以为这是很显然的,

可是终于有一天,人们给出了反例 ,推翻了这个结论

 

这是否意味着利用费马小定理的思想去判断素数的思想就是错误的呢?

答案是确定的。

可是若是咱们能够人为的把出错率降到很是小呢?

好比,对于一个数,咱们有$99.99999$%的概率作出正确判断,那这种算法不也很优越么?

 

因而Miller Rabin算法诞生了!

 

首先介绍一下二次探测定理

若$p$为素数,$a^{2}\equiv 1 \pmod P$,那么$a\equiv \pm 1 \pmod P$

证实

$a^{2}\equiv 1 \pmod P$

$a^{2}-1\equiv 0 \pmod P$

$(a+1)*(a-1)\equiv 0 \pmod P$

那么

$(a+1)\equiv 0 \pmod P$

或者

$(a-1)\equiv 0 \pmod P$

(此处可根据惟一分解定理证实)

$a\equiv \pm 1 \pmod P$

 

这个定理和素数断定有什么用呢?

首先,根据Miller Rabin算法的过程

假设须要判断的数是$p$

咱们把$p-1$分解为$2^k*t$的形式

当$p$是素数,有$a ^ {2^k * t} \equiv 1 \pmod p$

而后随机选择一个数$a$,计算出$a^t \pmod p$

让其不断的自乘,同时结合二次探测定理进行判断

若是咱们自乘后的数$\pmod p = 1$,可是以前的数$\pmod p \not = \pm 1$

那么这个数就是合数(违背了二次探测定理)

这样乘$k$次,最后获得的数就是$a^{p-1}$

那么若是最后计算出的数不为$1$,这个数也是合数(费马小定理)

正确性

老祖宗告诉咱们,若$p$经过一次测试,则$p$不是素数的几率为$25$%

那么通过$t$轮测试,$p$不是素数的几率为$\dfrac {1}{4^{t}}$

我习惯用$2,3,5,7,11,13,17,19$这几个数进行判断

在信息学范围内出错率为$0$%(不带高精)

code

注意在进行素数判断的时候须要用到快速幂。。

这个应该比较简单,就不细讲了

#include<cstdio>
#define LL long long 
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M, Test[10] = {2, 3, 5, 7, 11, 13, 17};
int pow(int a, int p, int mod) {
    int base = 1;
    for(; p; p >>= 1, a = (1ll * a * a) % mod) 
        if(p & 1) base = (1ll * base * a) % mod;
    return base % mod;
}
bool Query(int P) {
    if(P == 1) return 0;
    int t = P - 1, k = 0;
    while(!(t & 1)) k++, t >>= 1;
    for(int i = 0; i < 4; i++) {
        if(P == Test[i]) return 1;
        LL a = pow(Test[i], t, P), nxt = a;
        for(int j = 1; j <= k; j++) {
            nxt = (a * a) % P;
            if(nxt == 1 && a != 1 && a != P - 1) return 0;
            a = nxt;
        }
        if(a != 1) return 0;
    }
    return 1;
}
main() { 
    N = read(); M = read();    
    while(M--) puts(Query(read()) ? "Yes" : "No");
}
相关文章
相关标签/搜索