Miller-rabbin算法

本文介绍了一种利用费马小定理和Miller-Rabbin算法快速判断一个数是否为质数的方法。通过随机选取基数并利用特定的数学性质来提高判断效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个算法用于快速判断一个数是否是质数。
那怎么判呢?
首先,既然要快速,我们就不能用朴素的O(n)O(n)的试除法。我们会联想到质数的一些性质:

ap11 (mod p)(0<a<p)ap−1≡1 (mod p)(0<a<p)

也就是费马小定理了,我们可以由此想到一个简单的方法:随机一些a去判断ap1ap−1是否等于1。
然后按照套路的剧情发展,这个方法有毛病。
毛病在哪里呢?
你可以用这个方法试一下561=1151561=11∗51,看看能不能被判断出来。
这就是毛病了:存在像561一样的强伪素数,无论a选多少,得到的结果都是1。
怎么改进呢?
看另一个简单的定理:
如果对于一个偶数x有下列同余式(p为质数)
ax1 (mod p) (0<x<p)ax≡1 (mod p) (0<x<p)

那么
ax2±1 (mod p)ax2≡±1 (mod p)

为什么呢?
非常显然,由第一个式子可以得到
(ax2+1)(ax21)0 (mod p)p (mod p)(ax2+1)(ax2−1)≡0 (mod p)≡p (mod p)

因为p是一个质数,所以(ax2+1)(ax2+1)(ax21)(ax2−1)中必然有一项整除p,但是合数的话就不一定了。根据这个性质,我们就有了Miller-rabbin算法。
代码里有一些前人的经验,记不下来的话随机就好了。

Code

#include <iostream>
#include <cstring>
#include <cstdio>

typedef long long ll;

const int base[5] = {2, 3, 7, 61, 24251};

using namespace std;

inline ll read()
{
    ll X = 0; char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') X = X * 10 + ch - '0', ch = getchar();
    return X;
}

inline ll ksm(ll a, ll n, ll mod)
{
    ll b = 1;
    while (n) {
        if (n & 1) b = (__int128)a * b % mod;
        a = (__int128)a * a % mod;
        n >>= 1;
    }
    return b;
}

inline int miller_rabbin(ll n)
{
    if (n == 2 || n == 3 || n == 7 || n == 61 || n == 24251) return 1;
    if (n == 46856248255981ll || n < 2 || !(n & 1)) return 0;
    ll d = n - 1;
    while (!(d & 1)) d >>= 1;
    for (int i = 0; i < 5; i++) {
        ll t = ksm(base[i], d, n), k = d;
        for(; k != n - 1 && t != n - 1 && t != 1; k <<= 1)
            t = (__int128)t * t % n;
        if (t != n - 1 && (k & 1) != 1) return 0;
    }
    return 1;
}

int main(void)
{
    int t = read();
    while (t--) {
        ll n = read();
        printf(miller_rabbin(n) ? "Yes\n" : "No\n");
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值