跳转至

pollard-rho

约 20 个字 68 行代码 预计阅读时间 1 分钟

O(n^{\frac 14}) 得找到 x 的一个非1非本身的因子

ll fastPower(ll x, ll n, ll p)
{
    ll s = 1;
    for (; n; n >>= 1)
    {
        if (n & 1)
            s = (__int128)s*x%p;
        x=(__in128)x*x%p;
    }
    return s;
}
ll pollardRho(ll n)
{
    auto f = [&](ll x) { return (__int128)x*x%n + 1; };
    ll p = 2, q;
    for (ll i = 1, x = 0, y = 0, t = 0; t++ % 255 || __gcd(p, n) == 1; x = f(x), y = f(f(y)))
    {
        if (x == y)
        {
            x = i++;
            y = f(x);
        }
        q = (__int128)p*abs(x - y)%n;
        if (q)
            p = q;
    }
    return __gcd(p, n);
}
bool millerRabin(ll x)
{
    if (x < 3)
        return x == 2;
    if ((x&1) == 0)
        return false;
    ll v,r=__builtin_ctz(x-1),d=x>>r;
    for (ll a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022})
    {
        v = fastPower(a, d, x);
        if (v <= 1 || v == x - 1)
            continue;
        for (int i = 0; i < r; ++i)
        {
            v = (__int128)v * v % x; // 同样使用__int128过渡
            if (v == x - 1 && i != r - 1)
            {
                v = 1;
                break;
            }
            if (v == 1)
                return false;
        }
        if (v != 1)
            return false;
    }
    return true;
}
vector<ll> Primefactor;
void allPrimefactor(ll n)
{
    if (millerRabin(n))
    {
        Primefactor.push_back(n);
        return;
    }
    ll t = pollardRho(n);
    allPrimefactor(t);
    allPrimefactor(n / t);
}