P4718
要求找最大的素因子,考虑可能出现在因子的因子中,所以需要递归
i64 max_prime(i64 n)
{
if (isp(n)) {return n;}
i64 mx{std::numeric_limits<i64>::min()}; while (n != 1) {
auto div{findDiv(n)};
mx = std::max(mx, max_prime(div));//递归找最大素因子
n /= div;
}
return mx;
}
牛客多校第八场E
https://ac.nowcoder.com/acm/contest/81603/E
尽可能快地找出所有因子
先用 Pollard-Rho 快速找出所有质因子,再用质因子组合出所有因数
i64 mul(i64 a, i64 b, i64 m) {
return static_cast<__int128>(a) * b % m;
}
i64 power(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;
}
bool isprime(i64 n) {
if (n < 2)
return false;
static constexpr int A[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
int s = __builtin_ctzll(n - 1);
i64 d = (n - 1) >> s;
for (auto a : A) {
if (a == n)
return true;
i64 x = power(a, d, n);
if (x == 1 || x == n - 1)
continue;
bool ok = false;
for (int i = 0; i < s - 1; ++i) {
x = mul(x, x, n);
if (x == n - 1) {
ok = true;
break;
}
}
if (!ok)
return false;
}
return true;
}
std::vector<i64> factorize(i64 n) {//目的是进行因式分解,得出这个数的所有质因数
std::vector<i64> p;
std::function<void(i64)> f = [&](i64 n) {
if (n <= 10000) {
for (int i = 2; i * i <= n; ++i)
for (; n % i == 0; n /= i)
p.push_back(i);
if (n > 1)
p.push_back(n);
return;
}
if (isprime(n)) {
p.push_back(n);
return;
}
auto g = [&](i64 x) {
return (mul(x, x, n) + 1) % n;
};
i64 x0 = 2;
while (true) {
i64 x = x0;
i64 y = x0;
i64 d = 1;
i64 power = 1, lam = 0;
i64 v = 1;
while (d == 1) {
y = g(y);
++lam;
v = mul(v, std::abs(x - y), n);
if (lam % 127 == 0) {
d = std::gcd(v, n);
v = 1;
}
if (power == lam) {
x = y;
power *= 2;
lam = 0;
d = std::gcd(v, n);
v = 1;
}
}
if (d != n) {
f(d);
f(n / d);
return;
}
++x0;
}
};
f(n);
std::sort(p.begin(), p.end());
return p;
}
//通过质因数组合出所有因数
using factor = std::pair<i64, int>;//(质因数,有几个这个质因数)
std::vector<i64> GetDivisors(const std::vector<i64>& factors) {
std::unordered_map<i64, int> cnt;
for (auto fi : factors) {cnt[fi] += 1;}
std::vector<factor> fac_cnt(cnt.begin(), cnt.end());
std::vector<i64> divisors = {1};
for (auto &p : fac_cnt) {
int sz = divisors.size();
for (int i = 0; i < sz; i++) {
i64 cur = divisors[i];
for (int j = 0; j < p.second; j++) {
cur *= p.first;
divisors.push_back(cur);
}
}
}
//sort(divisors.begin(), divisors.end());
return divisors;
}
标签:std,cnt,return,Rho,i64,Pollard,vector,应用,divisors
From: https://www.cnblogs.com/kdlyh/p/18353185