This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
#define PROBLEM "https://yukicoder.me/problems/no/1659" #include <iostream> #include "../utils/macros.hpp" #include "../modulus/mint.hpp" #include "../number/primes.hpp" #include "../number/primes_extra.hpp" #include "../modulus/multichoose_simple.hpp" using namespace std; prepared_primes primes(1e6 + 100); constexpr int64_t MOD = 1000000007; mint<MOD> solve(int64_t n, int64_t k) { mint<MOD> ans = 1; for (auto [p, e] : list_prime_factors_as_map(primes, n)) { // ans *= multichoose_simple<MOD>(k, e); mint<MOD> y = 0; REP (x, e + 1) { y += multichoose_simple<MOD>(k, x); } ans *= y; } return ans; } // generated by oj-template v4.8.0 (https://github.com/online-judge-tools/template-generator) int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int64_t N, K; std::cin >> N >> K; auto ans = solve(N, K); std::cout << ans << '\n'; return 0; }
#line 1 "number/primes_extra.yukicoder-1659.test.cpp" #define PROBLEM "https://yukicoder.me/problems/no/1659" #include <iostream> #line 2 "utils/macros.hpp" #define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i)) #define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i)) #define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i)) #define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i)) #define ALL(x) std::begin(x), std::end(x) #line 2 "modulus/mint.hpp" #include <cstdint> #line 2 "modulus/modpow.hpp" #include <cassert> #line 4 "modulus/modpow.hpp" inline int32_t modpow(uint_fast64_t x, uint64_t k, int32_t MOD) { assert (/* 0 <= x and */ x < (uint_fast64_t)MOD); uint_fast64_t y = 1; for (; k; k >>= 1) { if (k & 1) (y *= x) %= MOD; (x *= x) %= MOD; } assert (/* 0 <= y and */ y < (uint_fast64_t)MOD); return y; } #line 2 "modulus/modinv.hpp" #include <algorithm> #line 5 "modulus/modinv.hpp" inline int32_t modinv_nocheck(int32_t value, int32_t MOD) { assert (0 <= value and value < MOD); if (value == 0) return -1; int64_t a = value, b = MOD; int64_t x = 0, y = 1; for (int64_t u = 1, v = 0; a; ) { int64_t q = b / a; x -= q * u; std::swap(x, u); y -= q * v; std::swap(y, v); b -= q * a; std::swap(b, a); } if (not (value * x + MOD * y == b and b == 1)) return -1; if (x < 0) x += MOD; assert (0 <= x and x < MOD); return x; } inline int32_t modinv(int32_t x, int32_t MOD) { int32_t y = modinv_nocheck(x, MOD); assert (y != -1); return y; } #line 6 "modulus/mint.hpp" /** * @brief quotient ring / 剰余環 $\mathbb{Z}/n\mathbb{Z}$ */ template <int32_t MOD> struct mint { int32_t value; mint() : value() {} mint(int64_t value_) : value(value_ < 0 ? value_ % MOD + MOD : value_ >= MOD ? value_ % MOD : value_) {} mint(int32_t value_, std::nullptr_t) : value(value_) {} explicit operator bool() const { return value; } inline mint<MOD> operator + (mint<MOD> other) const { return mint<MOD>(*this) += other; } inline mint<MOD> operator - (mint<MOD> other) const { return mint<MOD>(*this) -= other; } inline mint<MOD> operator * (mint<MOD> other) const { return mint<MOD>(*this) *= other; } inline mint<MOD> & operator += (mint<MOD> other) { this->value += other.value; if (this->value >= MOD) this->value -= MOD; return *this; } inline mint<MOD> & operator -= (mint<MOD> other) { this->value -= other.value; if (this->value < 0) this->value += MOD; return *this; } inline mint<MOD> & operator *= (mint<MOD> other) { this->value = (uint_fast64_t)this->value * other.value % MOD; return *this; } inline mint<MOD> operator - () const { return mint<MOD>(this->value ? MOD - this->value : 0, nullptr); } inline bool operator == (mint<MOD> other) const { return value == other.value; } inline bool operator != (mint<MOD> other) const { return value != other.value; } inline mint<MOD> pow(uint64_t k) const { return mint<MOD>(modpow(value, k, MOD), nullptr); } inline mint<MOD> inv() const { return mint<MOD>(modinv(value, MOD), nullptr); } inline mint<MOD> operator / (mint<MOD> other) const { return *this * other.inv(); } inline mint<MOD> & operator /= (mint<MOD> other) { return *this *= other.inv(); } }; template <int32_t MOD> mint<MOD> operator + (int64_t value, mint<MOD> n) { return mint<MOD>(value) + n; } template <int32_t MOD> mint<MOD> operator - (int64_t value, mint<MOD> n) { return mint<MOD>(value) - n; } template <int32_t MOD> mint<MOD> operator * (int64_t value, mint<MOD> n) { return mint<MOD>(value) * n; } template <int32_t MOD> mint<MOD> operator / (int64_t value, mint<MOD> n) { return mint<MOD>(value) / n; } template <int32_t MOD> std::istream & operator >> (std::istream & in, mint<MOD> & n) { int64_t value; in >> value; n = value; return in; } template <int32_t MOD> std::ostream & operator << (std::ostream & out, mint<MOD> n) { return out << n.value; } #line 5 "number/primes.hpp" #include <vector> #line 7 "number/primes.hpp" struct prepared_primes { int size; std::vector<int> sieve; std::vector<int> primes; /** * @note O(size) */ prepared_primes(int size_) : size(size_) { sieve.resize(size); REP3 (p, 2, size) if (sieve[p] == 0) { primes.push_back(p); for (int k = p; k < size; k += p) { if (sieve[k] == 0) { sieve[k] = p; } } } } /** * @note let k be the length of the result, O(k) if n < size; O(\sqrt{n} + k) if size <= n < size^2 */ std::vector<int64_t> list_prime_factors(int64_t n) const { assert (1 <= n and n < (int64_t)size * size); std::vector<int64_t> result; // trial division for large part for (int p : primes) { if (n < size or n < (int64_t)p * p) { break; } while (n % p == 0) { n /= p; result.push_back(p); } } // small part if (n == 1) { // nop } else if (n < size) { while (n != 1) { result.push_back(sieve[n]); n /= sieve[n]; } } else { result.push_back(n); } assert (std::is_sorted(ALL(result))); return result; } std::vector<int64_t> list_all_factors(int64_t n) const { auto p = list_prime_factors(n); std::vector<int64_t> d; d.push_back(1); for (int l = 0; l < p.size(); ) { int r = l + 1; while (r < p.size() and p[r] == p[l]) ++ r; int n = d.size(); REP (k1, r - l) { REP (k2, n) { d.push_back(d[d.size() - n] * p[l]); } } l = r; } return d; } /** * @note O(1) if n < size; O(sqrt n) if size <= n < size^2 */ bool is_prime(int64_t n) const { assert (1 <= n and n < (int64_t)size * size); if (n < size) { return sieve[n] == n; } for (int p : primes) { if (n < (int64_t)p * p) { break; } if (n % p == 0) { return false; } } return true; } }; #line 3 "number/primes_extra.hpp" #include <map> #line 7 "number/primes_extra.hpp" std::map<int64_t, int> list_prime_factors_as_map(const prepared_primes& primes, int64_t n) { std::map<int64_t, int> cnt; for (int64_t p : primes.list_prime_factors(n)) { ++ cnt[p]; } return cnt; } int64_t euler_totient(const prepared_primes& primes, int64_t n) { int64_t phi = 1; int64_t last = -1; for (int64_t p : primes.list_prime_factors(n)) { if (last != p) { last = p; phi *= p - 1; } else { phi *= p; } } return phi; } #line 5 "modulus/choose_simple.hpp" /** * @brief combination / 組合せ ${} _ n C _ r$ (愚直 $O(r)$) */ template <int32_t MOD> mint<MOD> choose_simple(int64_t n, int32_t r) { assert (0 <= r and r <= n); mint<MOD> num = 1; mint<MOD> den = 1; REP (i, r) { num *= n - i; den *= i + 1; } return num / den; } #line 5 "modulus/multichoose_simple.hpp" /** * @brief 重複組合せ ${} _ n H _ r = {} _ {n + r - 1} C _ r$ (愚直 $O(r)$) */ template <int32_t MOD> mint<MOD> multichoose_simple(int64_t n, int32_t r) { assert (0 <= n and 0 <= r); if (n == 0 and r == 0) return 1; return choose_simple<MOD>(n + r - 1, r); } #line 8 "number/primes_extra.yukicoder-1659.test.cpp" using namespace std; prepared_primes primes(1e6 + 100); constexpr int64_t MOD = 1000000007; mint<MOD> solve(int64_t n, int64_t k) { mint<MOD> ans = 1; for (auto [p, e] : list_prime_factors_as_map(primes, n)) { // ans *= multichoose_simple<MOD>(k, e); mint<MOD> y = 0; REP (x, e + 1) { y += multichoose_simple<MOD>(k, x); } ans *= y; } return ans; } // generated by oj-template v4.8.0 (https://github.com/online-judge-tools/template-generator) int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int64_t N, K; std::cin >> N >> K; auto ans = solve(N, K); std::cout << ans << '\n'; return 0; }