This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/factorize"
#include "../weilycoder/number-theory/factorize.hpp"
#include <iostream>
using namespace std;
using namespace weilycoder;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin.exceptions(cin.failbit | cin.badbit);
size_t t;
cin >> t;
while (t--) {
uint64_t x;
cin >> x;
auto primes = factorize<>(x);
cout << primes.size();
for (auto p : primes)
cout << ' ' << p;
cout << '\n';
}
return 0;
}#line 1 "test/factorize.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/factorize"
#line 1 "weilycoder/number-theory/factorize.hpp"
/**
* @file factorize.hpp
* @brief Functions for factorizing numbers using Pollard's Rho algorithm
*/
#line 1 "weilycoder/const_rand.hpp"
#include <cstdint>
namespace weilycoder {
/**
* @brief Linear Congruential Generator (LCG) to produce pseudo-random numbers
* at compile-time.
* @tparam a The multiplier.
* @tparam c The increment.
* @tparam m The modulus.
* @param state The current state of the generator.
* @return The next state of the generator.
*/
template <uint32_t a, uint32_t c, uint64_t m>
constexpr uint32_t &lcg_next(uint32_t &state) {
state = (static_cast<uint64_t>(a) * state + c) % m;
return state;
}
/**
* @brief LCG using parameters from "Minimal Standard" by Park and Miller.
* @param state The current state of the generator.
* @return The next state of the generator.
*/
constexpr uint32_t &lcg_minstd(uint32_t &state) {
return lcg_next<48271, 0, 2147483647>(state);
}
/**
* @brief LCG using parameters from "minstd_rand0" by Park and Miller.
* @param state The current state of the generator.
* @return The next state of the generator.
*/
constexpr uint32_t &lcg_minstd_rand0(uint32_t &state) {
return lcg_next<16807, 0, 2147483647>(state);
}
/**
* @brief LCG using parameters from "Numerical Recipes".
* @param state The current state of the generator.
* @return The next state of the generator.
*/
constexpr uint32_t &lcg_nr(uint32_t &state) {
return lcg_next<1103515245, 12345, 4294967296>(state);
}
} // namespace weilycoder
#line 1 "weilycoder/number-theory/mod_utility.hpp"
/**
* @file mod_utility.hpp
* @brief Modular Arithmetic Utilities
*/
#line 10 "weilycoder/number-theory/mod_utility.hpp"
namespace weilycoder {
using u128 = unsigned __int128;
template <bool bit32 = false>
constexpr uint64_t mod_add(uint64_t a, uint64_t b, uint64_t modulus) {
if constexpr (bit32) {
uint64_t res = a + b;
if (res >= modulus)
res -= modulus;
return res;
} else {
u128 res = static_cast<u128>(a) + b;
if (res >= modulus)
res -= modulus;
return res;
}
}
template <bool bit32 = false>
constexpr uint64_t mod_sub(uint64_t a, uint64_t b, uint64_t modulus) {
if constexpr (bit32) {
uint64_t res = (a >= b) ? (a - b) : (modulus + a - b);
return res;
} else {
u128 res = (a >= b) ? (a - b) : (static_cast<u128>(modulus) + a - b);
return res;
}
}
/**
* @brief Perform modular multiplication for 64-bit integers.
* @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that
* all inputs are small enough to avoid overflow (i.e. bit-32).
* @param a The first multiplicand.
* @param b The second multiplicand.
* @param modulus The modulus.
* @return (a * b) % modulus
*/
template <bool bit32 = false>
constexpr uint64_t mod_mul(uint64_t a, uint64_t b, uint64_t modulus) {
if constexpr (bit32)
return a * b % modulus;
else
return static_cast<u128>(a) * b % modulus;
}
/**
* @brief Perform modular multiplication for 64-bit integers with a compile-time
* modulus.
* @tparam Modulus The modulus.
* @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that
* all inputs are small enough to avoid overflow (i.e. bit-32).
* @param a The first multiplicand.
* @param b The second multiplicand.
* @return (a * b) % Modulus
*/
template <uint64_t Modulus, bool bit32 = false>
constexpr uint64_t mod_mul(uint64_t a, uint64_t b) {
if constexpr (bit32)
return a * b % Modulus;
else
return static_cast<u128>(a) * b % Modulus;
}
/**
* @brief Perform modular exponentiation for 64-bit integers.
* @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that
* all inputs are small enough to avoid overflow (i.e. bit-32).
* @param base The base number.
* @param exponent The exponent.
* @param modulus The modulus.
* @return (base^exponent) % modulus
*/
template <bool bit32 = false>
constexpr uint64_t mod_pow(uint64_t base, uint64_t exponent, uint64_t modulus) {
uint64_t result = 1 % modulus;
base %= modulus;
while (exponent > 0) {
if (exponent & 1)
result = mod_mul<bit32>(result, base, modulus);
base = mod_mul<bit32>(base, base, modulus);
exponent >>= 1;
}
return result;
}
} // namespace weilycoder
#line 1 "weilycoder/number-theory/prime.hpp"
/**
* @file prime.hpp
* @brief Prime Number Utilities
*/
#line 11 "weilycoder/number-theory/prime.hpp"
#include <type_traits>
namespace weilycoder {
/**
* @brief Miller-Rabin primality test for a given base.
* @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that
* all inputs are small enough to avoid overflow (i.e. bit-32).
* @tparam base The base to test.
* @param n The number to test for primality.
* @param d An odd component of n-1 (n-1 = d * 2^s).
* @param s The exponent of 2 in the factorization of n-1.
* @return true if n is probably prime for the given base, false if composite.
*/
template <bool bit32, uint64_t base>
constexpr bool miller_rabin_test(uint64_t n, uint64_t d, uint32_t s) {
uint64_t x = mod_pow<bit32>(base, d, n);
if (x == 0 || x == 1 || x == n - 1)
return true;
for (uint32_t r = 1; r < s; ++r) {
x = mod_mul<bit32>(x, x, n);
if (x == n - 1)
return true;
}
return false;
}
/**
* @brief Variadic template to test multiple bases in Miller-Rabin test.
* @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that
* all inputs are small enough to avoid overflow (i.e. bit-32).
* @tparam base The first base to test.
* @tparam Rest The remaining bases to test.
* @param n The number to test for primality.
* @param d An odd component of n-1 (n-1 = d * 2^s).
* @param s The exponent of 2 in the factorization of n-1.
* @return true if n is probably prime for all given bases, false if composite.
*/
template <bool bit32, uint64_t base, uint64_t... Rest>
constexpr std::enable_if_t<(sizeof...(Rest) != 0), bool>
miller_rabin_test(uint64_t n, uint64_t d, uint32_t s) {
return miller_rabin_test<bit32, base>(n, d, s) &&
miller_rabin_test<bit32, Rest...>(n, d, s);
}
/**
* @brief Miller-Rabin primality test using multiple bases.
* @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that
* all inputs are small enough to avoid overflow (i.e. bit-32).
* @tparam bases The bases to test.
* @param n The number to test for primality.
* @return true if n is probably prime, false if composite.
*/
template <bool bit32, uint64_t... bases> constexpr bool miller_rabin(uint64_t n) {
if (n < 2)
return false;
if (n == 2 || n == 3)
return true;
if (n % 2 == 0)
return false;
uint64_t d = n - 1, s = 0;
for (; d % 2 == 0; d /= 2)
++s;
return miller_rabin_test<bit32, bases...>(n, d, s);
}
/**
* @brief Miller-Rabin primality test optimized for 64-bit integers.
* Uses a fixed set of bases that guarantee correctness
* for 64-bit integers.
* @param n The number to test for primality.
* @return true if n is prime, false if not prime.
*/
constexpr bool miller_rabin64(uint64_t n) {
return miller_rabin<false, 2, 325, 9375, 28178, 450775, 9780504, 1795265022>(n);
}
/**
* @brief Miller-Rabin primality test optimized for 32-bit integers.
* Uses a fixed set of bases that guarantee correctness
* for 32-bit integers.
* @param n The number to test for primality.
* @return true if n is prime, false if not prime.
*/
constexpr bool miller_rabin32(uint32_t n) { return miller_rabin<true, 2, 7, 61>(n); }
constexpr bool is_prime(uint64_t n) {
if (n <= UINT32_MAX)
return miller_rabin32(static_cast<uint32_t>(n));
return miller_rabin64(n);
}
/**
* @brief Compile-time primality test for a given integer.
* @tparam x The integer to test for primality.
* @return true if x is prime, false otherwise.
*/
template <uint64_t x> constexpr bool is_prime() { return is_prime(x); }
} // namespace weilycoder
#line 12 "weilycoder/number-theory/factorize.hpp"
#include <algorithm>
#include <array>
#line 15 "weilycoder/number-theory/factorize.hpp"
#include <numeric>
#include <random>
#include <utility>
#include <vector>
namespace weilycoder {
/**
* @brief Pollard's Rho algorithm to find a non-trivial factor of x
* @tparam bit32 Whether to use 32-bit modular multiplication
* @param x The number to factorize
* @param c The constant in the polynomial x^2 + c
* @return A non-trivial factor of x
*/
template <bool bit32 = false> constexpr uint64_t pollard_rho(uint64_t x, uint64_t c) {
if (x % 2 == 0)
return 2;
c = c % (x - 1) + 1;
uint32_t step = 0, goal = 1;
uint64_t s = 0, t = 0;
uint64_t value = 1;
for (;; goal <<= 1, s = t, value = 1) {
for (step = 1; step <= goal; ++step) {
t = mod_mul<bit32>(t, t, x) + c;
if (t >= x)
t -= x;
uint64_t diff = (s >= t ? s - t : t - s);
value = mod_mul<bit32>(value, diff, x);
if (step % 127 == 0) {
uint64_t d = std::gcd(value, x);
if (d > 1)
return d;
}
}
uint64_t d = std::gcd(value, x);
if (d > 1)
return d;
}
return x;
}
/**
* @brief Pollard's Rho algorithm to find a non-trivial factor of x
* @tparam bit32 Whether to use 32-bit modular multiplication
* @param x The number to factorize
* @return A non-trivial factor of x
*/
template <bool bit32 = false> uint64_t pollard_rho(uint64_t x) {
if (x % 2 == 0)
return 2;
static std::minstd_rand rng{};
return pollard_rho<bit32>(x, rng());
}
/**
* @brief Factorize a number into its prime factors
* @tparam bit32 Whether to use 32-bit modular multiplication
* @param x The number to factorize
* @return A vector of prime factors of x
*/
template <bool bit32 = false> std::vector<uint64_t> factorize(uint64_t x) {
std::vector<uint64_t> factors;
std::vector<std::pair<uint64_t, size_t>> stk;
stk.emplace_back(x, 1);
while (!stk.empty()) {
auto [cur, cnt] = stk.back();
stk.pop_back();
if (cur == 1)
continue;
if (is_prime(cur)) {
factors.resize(factors.size() + cnt, cur);
continue;
}
uint64_t factor = cur;
do
factor = pollard_rho<bit32>(cur);
while (factor == cur);
size_t factor_count = 0;
while (cur % factor == 0)
cur /= factor, ++factor_count;
stk.emplace_back(cur, cnt);
stk.emplace_back(factor, factor_count * cnt);
}
std::sort(factors.begin(), factors.end());
return factors;
}
/**
* @brief Factorize a number into its prime factors with fixed-size array
* @tparam N The size of the output array
* @tparam bit32 Whether to use 32-bit modular multiplication
* @param x The number to factorize
* @return An array of prime factors of x
*/
template <size_t N = 64, bool bit32 = false>
constexpr std::array<uint64_t, N> factorize_fixed(uint64_t x) {
uint32_t random_state = 1;
size_t factor_idx = 0, stk_idx = 0;
std::array<uint64_t, N> factors{};
std::array<uint64_t, 64> stk_val{};
std::array<size_t, 64> stk_cnt{};
stk_val[stk_idx] = x, stk_cnt[stk_idx++] = 1;
while (stk_idx > 0) {
uint64_t cur = stk_val[--stk_idx];
size_t cnt = stk_cnt[stk_idx];
if (cur == 1)
continue;
if (is_prime(cur)) {
for (size_t i = 0; i < cnt; ++i)
factors[factor_idx++] = cur;
} else {
uint64_t factor = cur;
do
factor = pollard_rho<bit32>(cur, lcg_nr(random_state));
while (factor == cur);
size_t factor_count = 0;
while (cur % factor == 0)
cur /= factor, ++factor_count;
stk_val[stk_idx] = cur, stk_cnt[stk_idx++] = cnt;
stk_val[stk_idx] = factor, stk_cnt[stk_idx++] = factor_count * cnt;
}
}
for (size_t i = 1; i < factor_idx; ++i) {
uint64_t key = factors[i];
size_t j = i;
while (j > 0 && factors[j - 1] > key) {
factors[j] = factors[j - 1];
--j;
}
factors[j] = key;
}
return factors;
}
} // namespace weilycoder
#line 4 "test/factorize.test.cpp"
#include <iostream>
using namespace std;
using namespace weilycoder;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin.exceptions(cin.failbit | cin.badbit);
size_t t;
cin >> t;
while (t--) {
uint64_t x;
cin >> x;
auto primes = factorize<>(x);
cout << primes.size();
for (auto p : primes)
cout << ' ' << p;
cout << '\n';
}
return 0;
}