|
| 1 | +--- |
| 2 | +data: |
| 3 | + _extendedDependsOn: |
| 4 | + - icon: ':heavy_check_mark:' |
| 5 | + path: weilycoder/number-theory/factorize.hpp |
| 6 | + title: Functions for factorizing numbers using Pollard's Rho algorithm |
| 7 | + - icon: ':heavy_check_mark:' |
| 8 | + path: weilycoder/number-theory/mod_utility.hpp |
| 9 | + title: Modular Arithmetic Utilities |
| 10 | + - icon: ':heavy_check_mark:' |
| 11 | + path: weilycoder/number-theory/prime.hpp |
| 12 | + title: Prime Number Utilities |
| 13 | + _extendedRequiredBy: [] |
| 14 | + _extendedVerifiedWith: [] |
| 15 | + _isVerificationFailed: false |
| 16 | + _pathExtension: cpp |
| 17 | + _verificationStatusIcon: ':heavy_check_mark:' |
| 18 | + attributes: |
| 19 | + '*NOT_SPECIAL_COMMENTS*': '' |
| 20 | + PROBLEM: https://judge.yosupo.jp/problem/factorize |
| 21 | + links: |
| 22 | + - https://judge.yosupo.jp/problem/factorize |
| 23 | + bundledCode: "#line 1 \"test/factorize.test.cpp\"\n#define PROBLEM \"https://judge.yosupo.jp/problem/factorize\"\ |
| 24 | + \n\n#line 1 \"weilycoder/number-theory/factorize.hpp\"\n\n\n\n/**\n * @file factorize.hpp\n\ |
| 25 | + \ * @brief Functions for factorizing numbers using Pollard's Rho algorithm\n */\n\ |
| 26 | + \n#line 1 \"weilycoder/number-theory/mod_utility.hpp\"\n\n\n\n/**\n * @file mod_utility.hpp\n\ |
| 27 | + \ * @brief Modular Arithmetic Utilities\n */\n\n#include <cstdint>\n\nnamespace\ |
| 28 | + \ weilycoder {\n/**\n * @brief Perform modular multiplication for 64-bit integers.\n\ |
| 29 | + \ * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that\n\ |
| 30 | + \ * all inputs are small enough to avoid overflow (i.e. bit-32).\n * @param\ |
| 31 | + \ a The first multiplicand.\n * @param b The second multiplicand.\n * @param modulus\ |
| 32 | + \ The modulus.\n * @return (a * b) % modulus\n */\ntemplate <bool bit32 = false>\n\ |
| 33 | + uint64_t modular_multiply_64(uint64_t a, uint64_t b, uint64_t modulus) {\n if\ |
| 34 | + \ constexpr (bit32)\n return a * b % modulus;\n else\n return static_cast<unsigned\ |
| 35 | + \ __int128>(a) * b % modulus;\n}\n\n/**\n * @brief Perform modular multiplication\ |
| 36 | + \ for 64-bit integers with a compile-time\n * modulus.\n * @tparam Modulus\ |
| 37 | + \ The modulus.\n * @tparam bit32 If true, won't use 128-bit arithmetic. You should\ |
| 38 | + \ ensure that\n * all inputs are small enough to avoid overflow (i.e.\ |
| 39 | + \ bit-32).\n * @param a The first multiplicand.\n * @param b The second multiplicand.\n\ |
| 40 | + \ * @return (a * b) % Modulus\n */\ntemplate <uint64_t Modulus, bool bit32 = false>\n\ |
| 41 | + uint64_t modular_multiply_64(uint64_t a, uint64_t b) {\n if constexpr (bit32)\n\ |
| 42 | + \ return a * b % Modulus;\n else\n return static_cast<unsigned __int128>(a)\ |
| 43 | + \ * b % Modulus;\n}\n\n/**\n * @brief Perform modular exponentiation for 64-bit\ |
| 44 | + \ integers.\n * @tparam bit32 If true, won't use 128-bit arithmetic. You should\ |
| 45 | + \ ensure that\n * all inputs are small enough to avoid overflow (i.e.\ |
| 46 | + \ bit-32).\n * @param base The base number.\n * @param exponent The exponent.\n\ |
| 47 | + \ * @param modulus The modulus.\n * @return (base^exponent) % modulus\n */\ntemplate\ |
| 48 | + \ <bool bit32 = false>\nconstexpr uint64_t fast_power_64(uint64_t base, uint64_t\ |
| 49 | + \ exponent, uint64_t modulus) {\n uint64_t result = 1 % modulus;\n base %= modulus;\n\ |
| 50 | + \ while (exponent > 0) {\n if (exponent & 1)\n result = modular_multiply_64<bit32>(result,\ |
| 51 | + \ base, modulus);\n base = modular_multiply_64<bit32>(base, base, modulus);\n\ |
| 52 | + \ exponent >>= 1;\n }\n return result;\n}\n}\n\n\n#line 1 \"weilycoder/number-theory/prime.hpp\"\ |
| 53 | + \n\n\n\n/**\n * @file prime.hpp\n * @brief Prime Number Utilities\n */\n\n#line\ |
| 54 | + \ 11 \"weilycoder/number-theory/prime.hpp\"\n#include <type_traits>\n\nnamespace\ |
| 55 | + \ weilycoder {\n/**\n * @brief Miller-Rabin primality test for a given base.\n\ |
| 56 | + \ * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that\n\ |
| 57 | + \ * all inputs are small enough to avoid overflow (i.e. bit-32).\n * @tparam\ |
| 58 | + \ base The base to test.\n * @param n The number to test for primality.\n * @param\ |
| 59 | + \ d An odd component of n-1 (n-1 = d * 2^s).\n * @param s The exponent of 2 in\ |
| 60 | + \ the factorization of n-1.\n * @return true if n is probably prime for the given\ |
| 61 | + \ base, false if composite.\n */\ntemplate <bool bit32, uint64_t base>\nconstexpr\ |
| 62 | + \ bool miller_rabin_test(uint64_t n, uint64_t d, uint32_t s) {\n uint64_t x =\ |
| 63 | + \ fast_power_64<bit32>(base, d, n);\n if (x == 0 || x == 1 || x == n - 1)\n \ |
| 64 | + \ return true;\n for (uint32_t r = 1; r < s; ++r) {\n x = modular_multiply_64<bit32>(x,\ |
| 65 | + \ x, n);\n if (x == n - 1)\n return true;\n }\n return false;\n}\n\n\ |
| 66 | + /**\n * @brief Variadic template to test multiple bases in Miller-Rabin test.\n\ |
| 67 | + \ * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure that\n\ |
| 68 | + \ * all inputs are small enough to avoid overflow (i.e. bit-32).\n * @tparam\ |
| 69 | + \ base The first base to test.\n * @tparam Rest The remaining bases to test.\n\ |
| 70 | + \ * @param n The number to test for primality.\n * @param d An odd component of\ |
| 71 | + \ n-1 (n-1 = d * 2^s).\n * @param s The exponent of 2 in the factorization of\ |
| 72 | + \ n-1.\n * @return true if n is probably prime for all given bases, false if composite.\n\ |
| 73 | + \ */\ntemplate <bool bit32, uint64_t base, uint64_t... Rest>\nconstexpr std::enable_if_t<(sizeof...(Rest)\ |
| 74 | + \ != 0), bool>\nmiller_rabin_test(uint64_t n, uint64_t d, uint32_t s) {\n return\ |
| 75 | + \ miller_rabin_test<bit32, base>(n, d, s) &&\n miller_rabin_test<bit32,\ |
| 76 | + \ Rest...>(n, d, s);\n}\n\n/**\n * @brief Miller-Rabin primality test using multiple\ |
| 77 | + \ bases.\n * @tparam bit32 If true, won't use 128-bit arithmetic. You should ensure\ |
| 78 | + \ that\n * all inputs are small enough to avoid overflow (i.e. bit-32).\n\ |
| 79 | + \ * @tparam bases The bases to test.\n * @param n The number to test for primality.\n\ |
| 80 | + \ * @return true if n is probably prime, false if composite.\n */\ntemplate <bool\ |
| 81 | + \ bit32, uint64_t... bases> constexpr bool miller_rabin(uint64_t n) {\n if (n\ |
| 82 | + \ < 2)\n return false;\n if (n == 2 || n == 3)\n return true;\n if (n\ |
| 83 | + \ % 2 == 0)\n return false;\n\n uint64_t d = n - 1, s = 0;\n for (; d % 2\ |
| 84 | + \ == 0; d /= 2)\n ++s;\n\n return miller_rabin_test<bit32, bases...>(n, d,\ |
| 85 | + \ s);\n}\n\n/**\n * @brief Miller-Rabin primality test optimized for 64-bit integers.\n\ |
| 86 | + \ * Uses a fixed set of bases that guarantee correctness\n * for\ |
| 87 | + \ 64-bit integers.\n * @param n The number to test for primality.\n * @return\ |
| 88 | + \ true if n is prime, false if not prime.\n */\nconstexpr bool miller_rabin64(uint64_t\ |
| 89 | + \ n) {\n return miller_rabin<false, 2, 325, 9375, 28178, 450775, 9780504, 1795265022>(n);\n\ |
| 90 | + }\n\n/**\n * @brief Miller-Rabin primality test optimized for 32-bit integers.\n\ |
| 91 | + \ * Uses a fixed set of bases that guarantee correctness\n * for\ |
| 92 | + \ 32-bit integers.\n * @param n The number to test for primality.\n * @return\ |
| 93 | + \ true if n is prime, false if not prime.\n */\nconstexpr bool miller_rabin32(uint32_t\ |
| 94 | + \ n) { return miller_rabin<true, 2, 7, 61>(n); }\n\nconstexpr bool is_prime(uint64_t\ |
| 95 | + \ n) {\n if (n <= UINT32_MAX)\n return miller_rabin32(static_cast<uint32_t>(n));\n\ |
| 96 | + \ return miller_rabin64(n);\n}\n} // namespace weilycoder\n\n\n#line 11 \"weilycoder/number-theory/factorize.hpp\"\ |
| 97 | + \n#include <algorithm>\n#include <array>\n#line 14 \"weilycoder/number-theory/factorize.hpp\"\ |
| 98 | + \n#include <numeric>\n#include <random>\n#include <utility>\n#include <vector>\n\ |
| 99 | + \nnamespace weilycoder {\n/**\n * @brief Pollard's Rho algorithm to find a non-trivial\ |
| 100 | + \ factor of x\n * @tparam bit32 Whether to use 32-bit modular multiplication\n\ |
| 101 | + \ * @param x The number to factorize\n * @param c The constant in the polynomial\ |
| 102 | + \ x^2 + c\n * @return A non-trivial factor of x\n */\ntemplate <bool bit32 = false>\ |
| 103 | + \ constexpr uint64_t pollard_rho(uint64_t x, uint64_t c) {\n if (x % 2 == 0)\n\ |
| 104 | + \ return 2;\n uint32_t step = 0, goal = 1;\n uint64_t s = 0, t = 0;\n uint64_t\ |
| 105 | + \ value = 1;\n for (;; goal <<= 1, s = t, value = 1) {\n for (step = 1; step\ |
| 106 | + \ <= goal; ++step) {\n t = modular_multiply_64<bit32>(t, t, x) + c;\n \ |
| 107 | + \ if (t >= x)\n t -= x;\n uint64_t diff = (s >= t ? s - t : t -\ |
| 108 | + \ s);\n value = modular_multiply_64<bit32>(value, diff, x);\n if (step\ |
| 109 | + \ % 127 == 0) {\n uint64_t d = std::gcd(value, x);\n if (d > 1)\n\ |
| 110 | + \ return d;\n }\n }\n uint64_t d = std::gcd(value, x);\n \ |
| 111 | + \ if (d > 1)\n return d;\n }\n return x;\n}\n\n/**\n * @brief Pollard's\ |
| 112 | + \ Rho algorithm to find a non-trivial factor of x\n * @tparam bit32 Whether to\ |
| 113 | + \ use 32-bit modular multiplication\n * @param x The number to factorize\n * @return\ |
| 114 | + \ A non-trivial factor of x\n */\ntemplate <bool bit32 = false> uint64_t pollard_rho(uint64_t\ |
| 115 | + \ x) {\n static std::minstd_rand rng{};\n if (x % 2 == 0)\n return 2;\n \ |
| 116 | + \ uint64_t c = rng() % (x - 1) + 1;\n return pollard_rho<bit32>(x, c);\n}\n\n\ |
| 117 | + /**\n * @brief Factorize a number into its prime factors\n * @tparam bit32 Whether\ |
| 118 | + \ to use 32-bit modular multiplication\n * @param x The number to factorize\n\ |
| 119 | + \ * @return A vector of prime factors of x\n */\ntemplate <bool bit32 = false>\ |
| 120 | + \ std::vector<uint64_t> factorize(uint64_t x) {\n std::vector<uint64_t> factors;\n\ |
| 121 | + \ std::vector<std::pair<uint64_t, size_t>> stk;\n stk.emplace_back(x, 1);\n\ |
| 122 | + \ while (!stk.empty()) {\n auto [cur, cnt] = stk.back();\n stk.pop_back();\n\ |
| 123 | + \ if (cur == 1)\n continue;\n if (is_prime(cur)) {\n factors.resize(factors.size()\ |
| 124 | + \ + cnt, cur);\n continue;\n }\n uint64_t factor = cur;\n do\n \ |
| 125 | + \ factor = pollard_rho<bit32>(cur);\n while (factor == cur);\n size_t\ |
| 126 | + \ factor_count = 0;\n while (cur % factor == 0)\n cur /= factor, ++factor_count;\n\ |
| 127 | + \ stk.emplace_back(cur, cnt);\n stk.emplace_back(factor, factor_count *\ |
| 128 | + \ cnt);\n }\n std::sort(factors.begin(), factors.end());\n return factors;\n\ |
| 129 | + }\n\n/**\n * @brief Factorize a number into its prime factors with fixed-size\ |
| 130 | + \ array\n * @tparam N The size of the output array\n * @tparam bit32 Whether to\ |
| 131 | + \ use 32-bit modular multiplication\n * @param x The number to factorize\n * @return\ |
| 132 | + \ An array of prime factors of x\n */\ntemplate <size_t N = 64, bool bit32 = false>\n\ |
| 133 | + constexpr std::array<uint64_t, N> factorize_fixed(uint64_t x) {\n size_t factor_idx\ |
| 134 | + \ = 0, stk_idx = 0;\n std::array<uint64_t, N> factors{};\n std::array<std::pair<uint64_t,\ |
| 135 | + \ size_t>, 64> stk{};\n stk[stk_idx++] = {x, 1};\n while (stk_idx > 0) {\n \ |
| 136 | + \ auto [cur, cnt] = stk[--stk_idx];\n if (cur == 1)\n continue;\n \ |
| 137 | + \ if (is_prime(cur))\n std::fill(factors.begin() + factor_idx, factors.begin()\ |
| 138 | + \ + factor_idx + cnt, cur),\n factor_idx += cnt;\n else {\n uint64_t\ |
| 139 | + \ factor = cur;\n do\n factor = pollard_rho<bit32>(cur);\n while\ |
| 140 | + \ (factor == cur);\n size_t factor_count = 0;\n while (cur % factor\ |
| 141 | + \ == 0)\n cur /= factor, ++factor_count;\n stk[stk_idx++] = {cur,\ |
| 142 | + \ cnt};\n stk[stk_idx++] = {factor, factor_count * cnt};\n }\n }\n std::sort(factors.begin(),\ |
| 143 | + \ factors.begin() + factor_idx);\n return factors;\n}\n} // namespace weilycoder\n\ |
| 144 | + \n\n#line 4 \"test/factorize.test.cpp\"\n#include <iostream>\nusing namespace\ |
| 145 | + \ std;\nusing namespace weilycoder;\n\nint main() {\n cin.tie(nullptr)->sync_with_stdio(false);\n\ |
| 146 | + \ cin.exceptions(cin.failbit | cin.badbit);\n size_t t;\n cin >> t;\n while\ |
| 147 | + \ (t--) {\n uint64_t x;\n cin >> x;\n auto primes = factorize<>(x);\n\ |
| 148 | + \ cout << primes.size();\n for (auto p : primes)\n cout << ' ' << p;\n\ |
| 149 | + \ cout << '\\n';\n }\n return 0;\n}\n" |
| 150 | + code: "#define PROBLEM \"https://judge.yosupo.jp/problem/factorize\"\n\n#include\ |
| 151 | + \ \"../weilycoder/number-theory/factorize.hpp\"\n#include <iostream>\nusing namespace\ |
| 152 | + \ std;\nusing namespace weilycoder;\n\nint main() {\n cin.tie(nullptr)->sync_with_stdio(false);\n\ |
| 153 | + \ cin.exceptions(cin.failbit | cin.badbit);\n size_t t;\n cin >> t;\n while\ |
| 154 | + \ (t--) {\n uint64_t x;\n cin >> x;\n auto primes = factorize<>(x);\n\ |
| 155 | + \ cout << primes.size();\n for (auto p : primes)\n cout << ' ' << p;\n\ |
| 156 | + \ cout << '\\n';\n }\n return 0;\n}" |
| 157 | + dependsOn: |
| 158 | + - weilycoder/number-theory/factorize.hpp |
| 159 | + - weilycoder/number-theory/mod_utility.hpp |
| 160 | + - weilycoder/number-theory/prime.hpp |
| 161 | + isVerificationFile: true |
| 162 | + path: test/factorize.test.cpp |
| 163 | + requiredBy: [] |
| 164 | + timestamp: '2025-11-06 23:46:32+08:00' |
| 165 | + verificationStatus: TEST_ACCEPTED |
| 166 | + verifiedWith: [] |
| 167 | +documentation_of: test/factorize.test.cpp |
| 168 | +layout: document |
| 169 | +redirect_from: |
| 170 | +- /verify/test/factorize.test.cpp |
| 171 | +- /verify/test/factorize.test.cpp.html |
| 172 | +title: test/factorize.test.cpp |
| 173 | +--- |
0 commit comments