Miller–Rabin 素性测试

Miller–Rabin 素性测试

Miller–Rabin 素性测试(Miller–Rabin primality test)是进阶的素数判定方法。它是由 Miller 和 Rabin 二人根据费马小定理的逆定理(费马测试)优化得到的。因为和许多类似算法一样,它是使用伪素数的概率性测试,我们必须使用慢得多的确定性算法来保证素性。然而,实际上没有已知的数字通过了高级概率性测试(例如 Miller–Rabin)但实际上却是复合的。因此我们可以放心使用。

在不考虑乘法的复杂度时,对数 n n n 进行 k k k 轮测试的时间复杂度是 O ( k log ⁡ n ) O(k \log n) O(klogn)。Miller-Rabbin 素性测试常用于对高精度数进行测试,此时时间复杂度是 O ( k log ⁡ 3 n ) O(k \log^3n) O(klog3n),利用 FFT 等技术可以优化到 O ( k log ⁡ 2 n log ⁡ log ⁡ n log ⁡ log ⁡ log ⁡ n ) O(k \log^2n \log \log n \log \log \log n) O(klog2nloglognlogloglogn)

二次探测定理

如果 p p p 是奇素数,则 x 2 ≡ 1 ( m o d p ) x^2 \equiv 1 \pmod p x21(modp) 的解为 x ≡ 1 ( m o d p ) x \equiv 1 \pmod p x1(modp) 或者 x ≡ p − 1 ( m o d p ) x \equiv p - 1 \pmod p xp1(modp)

要证明该定理,只需将上面的方程移项,再使用平方差公式,得到 ( x + 1 ) ( x − 1 ) ≡ 0   m o d   p (x+1)(x-1) \equiv 0 \bmod p (x+1)(x1)0modp,即可得出上面的结论。

实现

根据卡迈克尔数的性质,可知其一定不是 p e p^e pe

不妨将费马小定理和二次探测定理结合起来使用:

a n − 1 ≡ 1 ( m o d n ) a^{n-1} \equiv 1 \pmod n an11(modn) 中的指数 n − 1 n−1 n1 分解为 n − 1 = u × 2 t n−1=u \times 2^t n1=u×2t,在每轮测试中对随机出来的 a a a 先求出 v = a u   m o d   n v = a^{u} \bmod n v=aumodn,之后对这个值执行最多 t t t 次平方操作,若发现非平凡平方根时即可判断出其不是素数,否则再使用 Fermat 素性测试判断。

还有一些实现上的小细节:

  • 对于一轮测试,如果某一时刻 a u × 2 s ≡ n − 1 ( m o d n ) a^{u \times 2^s} \equiv n-1 \pmod n au×2sn1(modn),则之后的平方操作全都会得到 1 1 1,则可以直接通过本轮测试。
  • 如果找出了一个非平凡平方根 a u × 2 s ≢ n − 1 ( m o d n ) a^{u \times 2^s} \not\equiv n-1 \pmod n au×2sn1(modn),则之后的平方操作全都会得到 1 1 1。可以选择直接返回 false,也可以放到 t t t 次平方操作后再返回 false

这样得到了较正确的 Miller Rabin。

代码:

bool MillerRabin(int n) {
    if (n == 2) return true;
    if (n <= 1 || n % 2 == 0) return false;
    ll base[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
    ll u = n - 1, k = 0;
    while (u % 2 == 0) u /= 2, k++;
    for (auto x : base) {
        if (x % n == 0) continue;
        ll v = powmod(x, u, n);
        if (v == 1 || v == n - 1) continue;
        for (int j = 1; j <= k; j++) {
            ll last = v;
            v = (__int128)v * v % n;
            if (v == 1) {
                if (last != n - 1) return false;
                break;
            }
        }
        if (v != 1) return false;
    }
    return true;
}

另外,假设 广义 Riemann 猜想(generalized Riemann hypothesis, GRH)成立,则对数 n n n 最多只需要测试 [ 2 , min ⁡ { n − 2 , ⌊ 2 ln ⁡ 2 n ⌋ } ] [2, \min\{n-2, \lfloor 2\ln^2 n \rfloor\}] [2,min{n2,2ln2n⌋}] 中的全部整数即可 确定 n n n 的素性。

而在 OI 范围内,通常都是对 [ 1 , 2 64 ) [1, 2^{64}) [1,264) 范围内的数进行素性检验。对于 [ 1 , 2 32 ) [1, 2^{32}) [1,232) 范围内的数,选取 { 2 , 7 , 61 } \{2, 7, 61\} {2,7,61} 三个数作为基底进行 Miller–Rabin 素性检验就可以确定素性;对于 [ 1 , 2 64 ) [1, 2^{64}) [1,264) 范围内的数,选取 { 2 , 325 , 9375 , 28178 , 450775 , 9780504 , 1795265022 } \{2, 325, 9375, 28178, 450775, 9780504, 1795265022\} {2,325,9375,28178,450775,9780504,1795265022} 七个数作为基底进行 Miller–Rabin 素性检验就可以确定素性。

也可以选取 { 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 } \{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37\} {2,3,5,7,11,13,17,19,23,29,31,37}(即前 12 12 12 个素数)检验 [ 1 , 2 64 ) [1, 2^{64}) [1,264) 范围内的素数。

注意如果要使用上面的数列中的数 a a a 作为基底判断 n n n 的素性:

  • 所有的数都要取一遍,不能只选小于 n n n 的;
  • a a a 换成 a   m o d   n a \bmod n amodn
  • 如果 a ≡ 0 ( m o d n ) a \equiv 0 \pmod n a0(modn),则直接通过该轮测试。

模板题:loj143

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int N = 200005;
const int INF = 0x3f3f3f3f;
ll powmod(__int128 x, ll y, ll mod) {
    ll res = 1;
    while (y) {
        if (y & 1) res = res * x % mod;
        y >>= 1;
        x = x * x % mod;
    }
    return res;
}
bool MillerRabin(ll n) {
    if (n == 2) return true;
    if (n <= 1 || n % 2 == 0) return false;
    ll base[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
    ll u = n - 1, k = 0;
    while (u % 2 == 0) u /= 2, k++;
    for (auto x : base) {
        if (x % n == 0) continue;
        ll v = powmod(x, u, n);
        if (v == 1 || v == n - 1) continue;
        for (int j = 1; j <= k; j++) {
            ll last = v;
            v = (__int128)v * v % n;
            if (v == 1) {
                if (last != n - 1) return false;
                break;
            }
        }
        if (v != 1) return false;
    }
    return true;
}
int main() {
    ll n;
    while (scanf("%lld", &n) != EOF) {
        if (Mr(n))
            printf("Y\n");
        else
            printf("N\n");
    }
    return 0;
}
  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Miller-Rabin素性测试算法是一种用于判断一个数是否为质数的算法。该算法基于费马小定理,使用随机数进行迭代运算,可以高效地判断一个数是否为质数。 具体来说,该算法将要判断的数记作n,随机选取一个小于n的正整数a,将a与n进行求模运算得到b。如果b等于0或者b等于n-1,则继续选择下一个a。否则,将b平方并对n取模,得到c。如果c等于1或者c等于n-1,则继续选择下一个a。否则,不断平方c并对n取模,直到c等于1或者迭代次数达到了一定阈值。如果c等于1,则n可能是一个合数;如果迭代过程中出现了c等于n-1的情况,则n很可能是一个质数。 为了提高判断的准确性,Miller-Rabin算法会进行多次随机迭代,每次选取不同的随机数a。随机迭代次数越多,判断结果的准确性越高,但计算时间也越长。 总之,Miller-Rabin素性测试算法是一种高效、准确的判断一个数是否为质数的算法,被广泛应用于密码学、计算机科学等领域。 ### 回答2: Miller-Rabin素性测试算法是一种用于判断一个数是否为素数的快速算法。该算法基于费马小定理,利用随机数的特性来判断一个数是否为素数。该算法的优势在于速度快且准确率高,同时能够应对大整数的素性测试。 该算法的具体步骤如下: 1. 首先确定待测试的数n,如果n为偶数,则直接判断n是否等于2,如果是则n为素数,因为2是最小的质数。 2. 若n为奇数,则写成n-1=2^r * d的形式,其中r为非负整数,d为奇数。 3. 接着随机选取一个整数a,且1 < a < n-1。计算a^d mod n,如果结果等于1或n-1,则可以认为n有很大的可能是素数,结束测试。 4. 若结果不等于1或n-1,则重复计算a^(2^j*d) mod n,直到出现下面两种情况之一:结果为1,或者出现了j=0,1,...,r-1时,结果为n-1。 5. 如果满足上述两种情况之一,则认为n有很大的可能是素数,结束测试。否则,重新随机选取一个a,重复上述操作进行测试。 需要说明的是,该算法的准确率可以通过多次测试进行提高。一般来说,重复进行10~20次检验,即可认为检验结果是正确的。 总之,Miller-Rabin素性测试算法是一种简单高效的素数测试算法,可以广泛应用于需要高精度计算的场合。它在加密、密码学等领域中,有着重要的应用价值。 ### 回答3: Miller-Rabin素性测试算法是一种用于判断一个数是否为素数的算法,名字来源于两位发明者:Gary L. Miller和Michael O. Rabin。与其它素数检测算法不同,Miller-Rabin素性测试算法有极高的概率能够正确地识别素数,其准确率可以达到误判的可能性小于$\frac{1}{4}$。 Miller-Rabin素性测试算法的基本原理是利用了费马小定理和欧拉判别法,即对于一个素数$p$和$a<p$,有$a^{p-1} \equiv 1 \pmod{p}$,而对于合数$n=pq$,其中$p,q$为大于1的素数,则在模n下,$a^{n-1} \equiv 1 \pmod{n}$,并且除了一些“小概率事件”外,$a^{(n-1)/2} \equiv \pm 1 \pmod{n}$。 Miller-Rabin 素性测试算法的流程如下: 1.将$n-1$分解成$2^sd$的形式,其中$d$是奇数。 2.对于给定的$a<n$,利用费马小定理,计算$a^d \pmod{n}$。 3.如果$a^d \equiv 1 \pmod{n}$,则认为$n$可能是一个素数,算法结束。 4.对于$0\leq r \leq s-1$,如果$a^{2^rd} \equiv -1 \pmod{n}$,则认为$n$可能是一个素数,算法结束。 5.如果$a^{2^sd} \not \equiv 1 \pmod{n}$或$a^{2^{r}d} \not \equiv -1 \pmod{n}$(其中$0\leq r \leq s-1$),则认为$n$不是素数,算法结束。 通过多次进行以上的步骤,可以提高算法的准确率。 Miller-Rabin素性测试算法是一种在计算机领域经常使用的算法,其特点是计算量较小、正确率较高、可扩展性好。在计算机安全领域,该算法被广泛地应用于RSA算法中,用于加密和解密数据。虽然该算法在某些情况下会出现一定的偏差,但是通过多次计算,可以达到一个非常高的准确率。因此,在实际应用中,Miller-Rabin素性测试算法是一个非常实用的工具。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值