Miller-Rabin学习笔记

为什么要学习Miller-Rabin ?

之前一直认为素性测试可以使用费马小定理的逆命题,虽说会有一定的概率判错,多选几个就好了。我现在才知道存在一种Carmichael Number。

对于任意与n互质的数x, 都有 x n − 1 = 1 ( m o d   n ) x^{n-1}=1 (mod\ n) xn1=1(mod n),那么n称作Carmichael Number。

可以发现,无论我们选择多少个素数x,都无法排除Carmichael Number,Miller-Rabin应运而生。

流程前的说明

我们需要一些引理和规定。

  • p p p为素数,且 x 2 = 1 ( m o d   p ) ( 0 &lt; x &lt; p ) x^2=1(mod\ p)(0 &lt; x &lt; p) x2=1(mod p)(0<x<p),则 x = 1 x=1 x=1 x = p − 1 x=p-1 x=p1
    证明如下:
    ∵ x 2 = 1 ( m o d   p ) \because x^2 = 1 (mod\ p) x2=1(mod p)
    ∴ x 2 − 1 = 0 ( m o d   p ) \therefore x^2 - 1 = 0 (mod\ p) x21=0(mod p)
    ∴ ( x + 1 ) ( x − 1 ) = 0 ( m o d   p ) \therefore (x + 1) (x - 1) = 0 (mod\ p) (x+1)(x1)=0(mod p)
    ∴ p ∣ ( x + 1 ) ( x − 1 ) \therefore p | (x + 1)(x - 1) p(x+1)(x1)
    ∵ p   i s   a   p r i m e \because p\ is\ a\ prime p is a prime
    ∴ x = 1 或 x = p − 1 \therefore x = 1 或 x = p - 1 x=1x=p1
  • 所以上面这个定理的逆否命题就是:若 x ! = 1 x!=1 x!=1 x ! = p − 1 x!=p-1 x!=p1,则p不为素数或 x 2 ! = 1 ( m o d p ) ( 0 &lt; x &lt; p ) x^2!=1(modp)(0 &lt; x &lt; p) x2!=1(modp)(0<x<p)。换言之,若 x ! = 1 x!=1 x!=1 x ! = p − 1 x!=p-1 x!=p1 x 2 = 1 ( m o d p ) ( 0 &lt; x &lt; p ) x^2=1(modp)(0 &lt; x &lt; p) x2=1(modp)(0<x<p),则 p p p一定不是质数,这一点在后面的代码里面有体现。
  • 下文中, n n n都是需要判断的数。
  • 下文的运算都是在 m o d   n mod\ n mod n意义下进行的。

Miller-Rabin的流程

这里介绍我认为比较好懂的一种表述。

1:判断 n n n是否是 2 2 2的倍数。

如果 n n n 2 2 2的倍数的话,有两种情况:

  • n = 2。2是唯一的偶质数,后面没法判断。我们需要把它单独处理。
  • n != 2。 它一定不是一个质数,我们就不用继续判断了。
2:把 n − 1 n-1 n1分解成 2 k ∗ m 2^k * m 2km的形式。

因为我们已经做了步骤1,所以 n n n一定是一个奇数。 n − 1 n-1 n1就一定可以分解成 2 k ∗ m 2^k * m 2km的形式。我们算出 k k k m m m

3:随机选择一个正整数 a a a,计算出Miller-Rabin序列

我们构造这样一个序列:
m 2 1 ∗ m 2 2 ∗ m ⋯ ⋯ 2 k ∗ m m\quad2^1*m\quad2^2*m\cdots\cdots\quad2^k*m m21m22m2km

构造这样一个序列有什么好处呢,我们发现:如果这个序列的每个数都是 a a a的次数的话,那么每一项可以由前一项平方得到。根据引理,我们可以通过判断 a 2 i ∗ m a^{2^i*m} a2im 1 1 1 n − 1 n-1 n1的关系来确定一个数不是质数。

4:判断 a 2 k ∗ m a^{2^k*m} a2km 1 1 1的关系

这里是根据费马小定理的逆命题,增大正确的机率。

5:重复步骤3、4,增大正确的机率。

正确性说明

可以证明单次Miller-Rabin的正确概率大于 3 4 \frac{3}{4} 43,我们重复若干次可以增大这个概率。

Miller-Rabin虽然有一定的概率出错,但在重复20次的情况下,实践证明1e7以内的质数不会判断出错。

复杂度说明

看具体实现,如果里面写了 O ( l o g n ) O(logn) O(logn)的大数乘法,复杂度就是 O ( l o g 2 n ) O(log^2n) O(log2n)的,否则是 O ( l o g n ) O(logn) O(logn)的。

typedef long long LL;
inline LL q_p(LL a, LL b, LL p) {
    LL res = 1;
    while (b) {
        if (b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
inline LL q_c(LL a, LL b, LL p) {
    return a * b - (LL)((LDB)a * b / p) * p;
}
inline int Miller_Rabin(LL n) {
    if (n == 2) return 1;
    if (n == 1 || !(n & 1)) return 0;
    LL k = 0, m = n - 1;
    while (!(m & 1)) {
        k++;
        m >>= 1;
    }
    for (int i = 1; i <= 20; ++i) {
        LL a = rand() % (n - 1) + 1;
        LL x = q_p(a, m, n), y;
        for (int j = 1; j <= k; ++j) {
            y = q_c(x, x, n);
            if (x != 1 && x != n - 1 && y == 1) return 0;
            x = y;
        }
        if (y != 1) return 0;
    }
    return 1;
}

后记

这是本人的第一篇blog, 由于本人水平有限,如有错漏之处请不吝指正。QQ:1902643000,欢迎一起讨论。

update

随机的整数a一定要在(0,n - 1)范围之内。但事实上,如果我们选择 2 , 3 , 7 , 61 , 24251 , 9875321 2,3,7,61,24251,9875321 2,3,7,61,24251,9875321这5个质数作为a的话,在 1 0 14 10^{14} 1014内不存在误判。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值