质因分解
暴力
cpp
auto factor(i64 n) {
std::vector<i64> ret;
for (int i = 2; i64(i) * i <= n; i++) {
for (; n % i == 0; n /= i)
ret.push_back(i);
}
if (n > 1)
ret.push_back(n);
return ret;
}
筛优化
cpp
auto factor(i64 n) {
std::vector<i64> ans;
for (int i : primes) {
if (1ll * i * i > n)
break;
for (; n % i == 0; n /= i)
ans.push_back(i);
}
if (n > 1)
ans.push_back(n);
return ans;
}
LPF 优化
cpp
auto factor(i64 n) {
std::vector<i64> ret;
for (; n > 1; n /= lpf[n])
ret.push_back(lpf[n]);
return ret;
}
Pollard Rho
cpp
i64 pollard_rho(i64 N) {
if (N % 2 == 0)
return 2;
if (miller_rabin(N))
return N;
while (true) {
auto f = [N, c = rand() % (N - 1) + 1](i64 x) {
return (i128(x) * x + c) % N;
};
i64 x = 0, y = 0, p = 1, q = 1;
do {
int w = 128;
do {
p = q, x = f(x), y = f(f(y));
q = i128(p) * std::abs(x - y) % N;
} while (w-- && q != 0);
i64 d = std::gcd(p, N);
if (d > 1 && d != N)
return d;
} while (x != y);
}
}
auto factor(i64 x) {
std::vector<i64> v;
if (x == 1)
return v;
auto dfs = [&](auto &&self, i64 u) -> void {
i64 fac = pollard_rho(u);
if (fac == u)
v.push_back(u);
else
self(self, fac), self(self, u / fac);
};
dfs(dfs, x);
std::sort(v.begin(), v.end());
return v;
}
cpp
using i128 = __int128_t;
i64 qpow64(i64 a, i64 n, i64 m) {
i64 ret = 1 % m;
for (; n; n /= 2) {
if (n & 1)
ret = i128(a) * ret % m;
a = i128(a) * a % m;
}
return ret;
}
bool is_prime_small(i64 n) {
if (n < 64)
return (0x28208a20a08a28ac >> n) & 1;
if ((0xdf75d77d >> (n % 30)) & 1)
return false;
if (n % 7 == 0 || n % 11 == 0)
return false;
return true;
}
bool miller_rabin(i64 n) {
if (!is_prime_small(n))
return false;
i64 a = n - 1;
a /= a & -a;
for (int p : {2, 3, 5, 7, 11, 13, 17, 19, 23}) {
if (n <= p)
return true;
i64 t = a, v = qpow64(p, t, n);
while (t != n - 1 && v != 1 && v != n - 1)
v = i128(v) * v % n, t *= 2;
if (v != n - 1 && t % 2 == 0)
return false;
}
return true;
}
i64 pollard_rho(i64 N) {
if (N % 2 == 0)
return 2;
if (miller_rabin(N))
return N;
while (true) {
auto f = [N, c = rand() % (N - 1) + 1](i64 x) {
return (i128(x) * x + c) % N;
};
i64 x = 0, y = 0, p = 1, q = 1;
do {
int w = 128;
do {
p = q, x = f(x), y = f(f(y));
q = i128(p) * std::abs(x - y) % N;
} while (w-- && q != 0);
i64 d = std::gcd(p, N);
if (d > 1 && d != N)
return d;
} while (x != y);
}
}
auto factor(i64 x) {
std::vector<i64> v;
if (x == 1)
return v;
auto dfs = [&](auto &&self, i64 u) -> void {
i64 fac = pollard_rho(u);
if (fac == u)
v.push_back(u);
else
self(self, fac), self(self, u / fac);
};
dfs(dfs, x);
std::sort(v.begin(), v.end());
return v;
}