【数学】MillerRabin算法

原理

目标:检测某个较大的正整数 \(n\) 是否为质数。

证明:

\(n \leq 2\) 则直接给出结果。否则,若 \(n\) 为偶数,也直接给出结果。

否则,假设 \(n\) 为奇质数,显然 \(n-1\) 为偶数,可以写成 \(2^sd\) 的形式,其中 \(s\) 是正整数,而 \(d\) 是奇数。则对于任意 \(a\)\(0\leq r\leq s-1\) ,必定满足以下两种形式的一种:

\(a^d\equiv 1 \pmod{n}\)\(a^{2^rd}\equiv -1 \pmod{n}\)

因为,由于费马小定理,若 \(n\) 为质数,则 \(a^{n-1}\equiv 1 \pmod{n}\) (反之不成立)。

代码

ll qmul(ll a, ll b, ll mod) {
    return (__int128)a * b % mod;
}

ll qpow(ll a, ll b, ll mod) {
    if(a >= mod)
        a %= mod;
    ll res = 1;
    while(b) {
        if(b & 1)
            res = qmul(res, a, mod);
        a = qmul(a, a, mod);
        b >>= 1;
    }
    return res;
}

namespace MillerRabin {

    // private
    bool MR(ll n, ll p) {
        for(ll k = n - 1; k; k >>= 1) {
            ll t = qpow(p, k, n);
            if(t != 1 && t != n - 1)
                return false;
            if((k & 1) == 1 || t == n - 1)
                // probably true
                return true;
        }
        // probably true
        return true;
    }

    // public
    bool isPrime(ll n) {
        if(n <= 1)
            return false;
        if(n <= 3)
            return true;
        if(!(n & 1))
            return false;
        static int basePrime[5] = {2, 3, 7, 61, 24251};
        for(int i = 1; i <= 5; ++i) {
            if(n == basePrime[i - 1])
                return true;
            if(!MR(n, basePrime[i - 1]))
                return false;
        }
        if(n == 46856248255981LL)
            return false;
        // probably true
        return true;
    }

}

using namespace MillerRabin;

check函数的意图是用质数p作为基检查x是否为质数。

首先排除掉相等的情况,然后排除掉x已经有p作为质数的情况。然后后续p只会出现在快速幂中,所以先进行一次取模。先用费马小定理确定x不是质数。

posted @ 2020-09-16 00:02  purinliang  阅读(326)  评论(0编辑  收藏  举报