Pollard_Rho 算法

Pollard_Rho

以下为分解最大质因子代码。

#include <ctime>
#include <iostream>

using i64 = long long;

#define DEBUG() std::cerr << __FUNCTION__ << " " << __LINE__ << std::endl
#define ctz __builtin_ctzll

i64 gcd(i64 a, i64 b);
i64 pow(i64 a, i64 k, i64 p);
i64 mul(i64 a, i64 b, i64 p);
int Miller_Rabin(i64 n);
void Pollard_Rho(i64 n);

int t;
i64 n, MaxFactor = 1;

int main() {
    srand(time(0));
    
    scanf("%d", &t);
    while (t--)
        scanf("%lld", &n), MaxFactor = 1, Pollard_Rho(n),
        MaxFactor == n ? printf("Prime\n") : printf("%lld\n", MaxFactor);

    return 0;
}

i64 gcd(i64 a, i64 b) {
//  return b ? gcd(b, a % b) : a;
    int shift = ctz(a | b);
    b >>= ctz(b);
    while (a) {
        a >>= ctz(a);
        if (a < b) std::swap(a, b);
        a -= b;
    }
    return b << shift;
}
i64 pow(i64 a, i64 k, i64 p) {
    i64 t = 1;
    for (; k; a = mul(a, a, p), k >>= 1) if (k & 1) t = mul(t, a, p);
    return t;
}
i64 mul(i64 a, i64 b, i64 p) {
    i64 c = (a * b - (i64)((long double)a * b / p + 1e-9) * p) % p;
    return c < 0 ? c + p : c;
}

int Miller_Rabin(i64 n) {
    static const i64 P[] = { 2, 325, 9375, 28178, 450775, 9780504, 1795265022, 0 };
    if (n < 2) return 0;
    i64 m = n - 1, a, b; int k = 0;
    while (!(m & 1)) m >>= 1, ++k;
    for (int i = 0; P[i]; ++i) {
        if (!(a = P[i] % n)) return 1;
        a = b = pow(a, m, n);
        for (int j = 1; j <= k; ++j, a = b)
            if ((b = mul(a, a, n)) == 1 && a != 1 && a != n - 1) return 0;
        if (a != 1) return 0;
    }
    return 1;
}

void Pollard_Rho(i64 n) {
    if (n <= MaxFactor) return;
    if (n == 1 || Miller_Rabin(n)) { MaxFactor = n; return; }
    
    auto find = [](i64 n) {
        static const int LIM = 1 << 22;
        i64 x = rand() % n, y, z, w, c = rand() % (n - 1) + 1;
        for (int i = 1; i <= LIM; i <<= 1) {
            y = x, z = 1;
            for (int j = 1; j <= i; ++j) {
                x = (mul(x, x, n) + c) % n;
                z = mul(z, std::abs(x - y), n);
                if (j % 127 == 0 && (w = gcd(z, n)) > 1) return w;
            }
            if ((w = gcd(z, n)) > 1) return w;
        }
        return n;
    };
    i64 d;
    for (d = n; d == n; d = find(n));
    while (n % d == 0) n /= d;
    Pollard_Rho(d), Pollard_Rho(n);
}

猜你喜欢

转载自www.cnblogs.com/Ryedii-blog/p/12448697.html