判断素数的几种方法

介绍

1、素数计算函数:令小于等于 \(x\) 的素数个数为函数 \(pi(x)\),则随着 \(x\) 的增大,\(pi(x)\) 趋近于 \(\frac{x}{lnx}\)

素数判断

1、埃氏筛:\(O(sqrt(n))\)

inline bool ispreim(i64 x) {
    if (x == 0 || x == 1) return false;
    for (i64 i = 2; i <= x / i; i++) {
        if (x % i == 0) return false;
    }
    return true;
}

2、\(Miller-Rabin\) 筛:\(O(log(n))\)

struct MR{
    inline i64 mul(i64 a, i64 b, i64 m) {
        return static_cast<i128>(a) * b % m;
    }
    
    inline i64 qp(i64 a, i64 b, i64 m) {
        i64 res = 1 % m;
        for (; b; b >>= 1, a = mul(a, a, m))
            if (b & 1)
                res = mul(res, a, m);
        return res;
    }
    
    inline bool isprime(i64 n) {
        if (n < 2)
            return false;
        static constexpr i64 A[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
        i64 s = __builtin_ctzll(n - 1);
        i64 d = (n - 1) >> s;
        for (auto a : A) {
            if (a == n)
                return true;
            i64 x = qp(a, d, n);
            if (x == 1 || x == n - 1)
                continue;
            bool ok = false;
            for (i64 i = 0; i < s - 1; ++i) {
                x = mul(x, x, n);
                if (x == n - 1) {
                    ok = true;
                    break;
                }
            }
            if (!ok)
                return false;
        }
        return true;
    }
};

3、线性筛也叫欧拉筛 :\(O(n)\)的预处理时间

模版:洛谷P3383

struct pre{
    int N;
    vector<i64> preim;
    vector<i64> a;
    pre(int N_) : a(N_ + 1) {
        N = N_;
        for (i64 i = 2; i <= N; i++) {
            if (!a[i]) {
                a[i] = i;
                preim.push_back(i);
            }
            for (auto p : preim) {
                if (i * p > N) break;
                a[i * p] = p;
                if (a[i] == p) {
                    break;
                }
            }
        }
    }
    
    inline bool ispreim(i64 x) {
        return (a[x] == x && x != 0);
    }
};
posted @ 2024-08-30 22:33  grape_king  阅读(143)  评论(0)    收藏  举报