Skip to content

Commit 470cde3

Browse files
committed
feat: Implement factorization functions and add test cases
1 parent bf6b463 commit 470cde3

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

test/factorize.test.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/factorize"
2+
3+
#include "../weilycoder/number-theory/factorize.hpp"
4+
#include <iostream>
5+
using namespace std;
6+
using namespace weilycoder;
7+
8+
int main() {
9+
cin.tie(nullptr)->sync_with_stdio(false);
10+
cin.exceptions(cin.failbit | cin.badbit);
11+
size_t t;
12+
cin >> t;
13+
while (t--) {
14+
uint64_t x;
15+
cin >> x;
16+
auto primes = factorize<>(x);
17+
cout << primes.size();
18+
for (auto p : primes)
19+
cout << ' ' << p;
20+
cout << '\n';
21+
}
22+
return 0;
23+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#ifndef WEILYCODER_NUMBER_THEORY_FACTORIZE_HPP
2+
#define WEILYCODER_NUMBER_THEORY_FACTORIZE_HPP
3+
4+
#include "mod_utility.hpp"
5+
#include "prime.hpp"
6+
#include <algorithm>
7+
#include <array>
8+
#include <cstdint>
9+
#include <numeric>
10+
#include <random>
11+
#include <utility>
12+
#include <vector>
13+
14+
namespace weilycoder {
15+
template <bool bit32 = false> constexpr uint64_t pollard_rho(uint64_t x, uint64_t c) {
16+
if (x % 2 == 0)
17+
return 2;
18+
uint32_t step = 0, goal = 1;
19+
uint64_t s = 0, t = 0;
20+
uint64_t value = 1;
21+
for (;; goal <<= 1, s = t, value = 1) {
22+
for (step = 1; step <= goal; ++step) {
23+
t = modular_multiply_64<bit32>(t, t, x) + c;
24+
if (t >= x)
25+
t -= x;
26+
uint64_t diff = (s >= t ? s - t : t - s);
27+
value = modular_multiply_64<bit32>(value, diff, x);
28+
if (step % 127 == 0) {
29+
uint64_t d = std::gcd(value, x);
30+
if (d > 1)
31+
return d;
32+
}
33+
}
34+
uint64_t d = std::gcd(value, x);
35+
if (d > 1)
36+
return d;
37+
}
38+
return x;
39+
}
40+
41+
template <bool bit32 = false> uint64_t pollard_rho(uint64_t x) {
42+
static std::minstd_rand rng{};
43+
if (x % 2 == 0)
44+
return 2;
45+
uint64_t c = rng() % (x - 1) + 1;
46+
return pollard_rho<bit32>(x, c);
47+
}
48+
49+
template <bool bit32 = false> std::vector<uint64_t> factorize(uint64_t x) {
50+
std::vector<uint64_t> factors;
51+
std::vector<std::pair<uint64_t, size_t>> stk;
52+
stk.emplace_back(x, 1);
53+
while (!stk.empty()) {
54+
auto [cur, cnt] = stk.back();
55+
stk.pop_back();
56+
if (cur == 1)
57+
continue;
58+
if (is_prime(cur)) {
59+
factors.resize(factors.size() + cnt, cur);
60+
continue;
61+
}
62+
uint64_t factor = cur;
63+
do
64+
factor = pollard_rho<bit32>(cur);
65+
while (factor == cur);
66+
size_t factor_count = 0;
67+
while (cur % factor == 0)
68+
cur /= factor, ++factor_count;
69+
stk.emplace_back(cur, cnt);
70+
stk.emplace_back(factor, factor_count * cnt);
71+
}
72+
std::sort(factors.begin(), factors.end());
73+
return factors;
74+
}
75+
76+
template <size_t N = 64, bool bit32 = false>
77+
constexpr std::array<uint64_t, N> factorize_fixed(uint64_t x) {
78+
size_t factor_idx = 0, stk_idx = 0;
79+
std::array<uint64_t, N> factors{};
80+
std::array<std::pair<uint64_t, size_t>, 64> stk{};
81+
stk[stk_idx++] = {x, 1};
82+
while (stk_idx > 0) {
83+
auto [cur, cnt] = stk[--stk_idx];
84+
if (cur == 1)
85+
continue;
86+
if (is_prime(cur))
87+
std::fill(factors.begin() + factor_idx, factors.begin() + factor_idx + cnt, cur),
88+
factor_idx += cnt;
89+
else {
90+
uint64_t factor = cur;
91+
do
92+
factor = pollard_rho<bit32>(cur);
93+
while (factor == cur);
94+
size_t factor_count = 0;
95+
while (cur % factor == 0)
96+
cur /= factor, ++factor_count;
97+
stk[stk_idx++] = {cur, cnt};
98+
stk[stk_idx++] = {factor, factor_count * cnt};
99+
}
100+
}
101+
std::sort(factors.begin(), factors.begin() + factor_idx);
102+
return factors;
103+
}
104+
} // namespace weilycoder
105+
106+
#endif

0 commit comments

Comments
 (0)