#ifndef ONLINE_JUDGE #define _GLIBCXX_DEBUG #endif #include "atcoder/all" #include #include #include #include #include #include #include // 任意長整数型 using Bint = boost::multiprecision::cpp_int; // 仮数部が10進数で1024桁の浮動小数点数型(TLEしたら小さくする) using BReal = boost::multiprecision::number>; using Rat = boost::rational; #include #include #include #include using namespace std; using namespace __gnu_pbds; // 型エイリアスの設定 template using ordered_set = tree, rb_tree_tag, tree_order_statistics_node_update>; using namespace atcoder; template inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template inline bool chmin(T &a, T b) { return ((a>b) ? (a = b, true) : (false));} #define rep(i,n) for(int i=0;i<(int)(n);i++) #define drep(i,n) for(int i=n-1;i>=0;i--) #define REP(i,s,n) for(int i=s;i<(int)n;i++) #define DREP(i,s,n) for(int i=n-1;i>=s;i--) const long long inf = 1LL<<60; const int infi = 1e9+1; typedef long long ll; typedef long double ld; typedef __int128_t l3; //cmpArg := 偏角ソート, atan2l(y, x); atan2l(y, x) = [-pi, pi] #define cmpArg [](const auto &p1, const auto &p2) { return atan2l(p1.second, p1.first) < atan2l(p2.second, p2.first); } typedef pair pi; typedef pair pl; typedef unsigned long long ull; #define vl vector #define vvl vector> #define vi vector #define vvi vector> #define vm vector #define vvm vector> #define vvc vector> #define vc vector #define vvpi vector> #define vpi vector #define vpl vector #define vvpl vector> #define pb push_back #define eb emplace_back #define YES cout<<"Yes"<> a; } inline void read(unsigned &a) { std::cin >> a; } inline void read(long &a) { std::cin >> a; } inline void read(long long &a) { std::cin >> a; } inline void read(unsigned long long &a) { std::cin >> a; } inline void read(char &a) { std::cin >> a; } inline void read(float &a) { std::cin >> a; } inline void read(double &a) { std::cin >> a; } inline void read(long double &a) { std::cin >> a; } inline void read(std::vector &vec) { for (int32_t i = 0; i < vec.size(); i++) { int a; read(a); vec[i] = a; } } inline void read(std::string &a) { std::cin >> a; } template inline void read(std::vector &vec); template inline void read(std::array &vec); template inline void read(std::pair &p); template inline void read(T (&vec)[size]); template inline void read(std::vector &vec) { for (auto &i : vec) read(i); } template inline void read(std::deque &vec) { for (auto &i : vec) read(i); } template inline void read(std::array &vec) { for (auto &i : vec) read(i); } template inline void read(std::pair &p) { read(p.first); read(p.second); } template inline void read(T (&vec)[size]) { for (auto &i : vec) read(i); } template inline void read(T &a) { std::cin >> a; } inline void in() {} template inline void in(Head &head, Tail &...tail) { read(head); in(tail...); } inline void print() { std::cout << ' '; } inline void print(const bool &a) { std::cout << a; } inline void print(const int &a) { std::cout << a; } inline void print(const unsigned &a) { std::cout << a; } inline void print(const long &a) { std::cout << a; } inline void print(const long long &a) { std::cout << a; } inline void print(const unsigned long long &a) { std::cout << a; } inline void print(const char &a) { std::cout << a; } inline void print(const char a[]) { std::cout << a; } inline void print(const float &a) { std::cout << a; } inline void print(const double &a) { std::cout << a; } inline void print(const long double &a) { std::cout << a; } inline void print(const std::string &a) { for (auto &&i : a) print(i); } template inline void print(const std::vector &vec); template inline void print(const std::array &vec); template inline void print(const std::pair &p); template inline void print(const T (&vec)[size]); template inline void print(const std::vector &vec) { if (vec.empty()) return; print(vec[0]); for (auto i = vec.begin(); ++i != vec.end();) { std::cout << ' '; print(*i); } } template inline void print(const std::deque &vec) { if (vec.empty()) return; print(vec[0]); for (auto i = vec.begin(); ++i != vec.end();) { std::cout << ' '; print(*i); } } template inline void print(const std::array &vec) { print(vec[0]); for (auto i = vec.begin(); ++i != vec.end();) { std::cout << ' '; print(*i); } } template inline void print(const std::pair &p) { print(p.first); std::cout << ' '; print(p.second); } template inline void print(const T (&vec)[size]) { print(vec[0]); for (auto i = vec; ++i != end(vec);) { std::cout << ' '; print(*i); } } template inline void print(const T &a) { std::cout << a; } inline void out() { std::cout << '\n'; } template inline void out(const T &t) { print(t); std::cout << '\n'; } template inline void out(const Head &head, const Tail &...tail) { print(head); std::cout << ' '; out(tail...); } #define vec(type, name, ...) vector name(__VA_ARGS__); #define vv(type, name, h, ...) std::vector> name(h, std::vector(__VA_ARGS__)); #define INT(...) int32_t __VA_ARGS__; in(__VA_ARGS__) #define LL(...) int64_t __VA_ARGS__; in(__VA_ARGS__) #define ULL(...) uint64_t __VA_ARGS__; in(__VA_ARGS__) #define STR(...) std::string __VA_ARGS__; in(__VA_ARGS__) #define CHR(...) char __VA_ARGS__; in(__VA_ARGS__) #define LD(...) long double __VA_ARGS__; in(__VA_ARGS__) #define VEC(type, name, size) std::vector name(size); in(name) #define VV(type, name, h, w) std::vector> name(h, std::vector(w)); in(name) template ll sum(const T &a) { return accumulate(std::begin(a), std::end(a), 0LL); } template ld dsum(const T &a) { return accumulate(std::begin(a), std::end(a), 0.0L); } template auto min(const T &a) { return *min_element(std::begin(a), std::end(a)); } template auto max(const T &a) { return *max_element(std::begin(a), std::end(a)); } template T floor_div(const T n, const T d) { assert(d != 0); return n / d - static_cast((n ^ d) < 0 && n % d != 0); } template T ceil_div(const T n, const T d) { assert(d != 0); return n / d + static_cast((n ^ d) >= 0 && n % d != 0); } using mint = modint998244353; namespace asalib { namespace math { template constexpr bool miller_rabin_test(T n) { if (n < 2) [[unlikely]] return false; if (n % 2 == 0) return n == 2; T d = n - 1, s = 0; while (d % 2 == 0) d >>= 1, ++s; assert(d % 2 == 1); static_assert(sizeof(T) == 4 || sizeof(T) == 8, "T must be 32-bit or 64-bit integer type"); constexpr bool is_64bit = sizeof(T) == 8; function modpow = [&](T a, T n, T mod) { T res = 1; while (n) { if constexpr (is_64bit) { if (n & 1) res = (__uint128_t) res * a % mod; a = (__uint128_t) a * a % mod; } else { if (n & 1) res = (unsigned long long) res * a % mod; a = (unsigned long long) a * a % mod; } n >>= 1; } return res; }; function test = [&](T a) { T x = modpow(a, d, n); if (x == 0) [[unlikely]] return false; if (x == 1) [[unlikely]] return true; for (T _ = 0; _ < s; ++_) { T y; if constexpr (is_64bit) y = (__uint128_t) x * x % n; else y = (unsigned long long) x * x % n; if (y == 1 && x != 1 && x != n - 1) return false; x = y; } return x == 1; }; function)> tests = [&](vector basis) { for (T a : basis) if (!test(a)) return false; return true; }; if (n < 2'047) return test(2); if (n < 1'373'653) return tests({ 2, 3 }); if (n < 9'080'191) return tests({ 31, 73 }); if (n < 25'326'001) return tests({ 2, 3, 5 }); if (n < 3'215'031'751) return tests({ 2, 3, 5, 7 }); if (n < 4'759'123'141) return tests({ 2, 7, 61 }); if (n < 1'122'004'669'633) return tests({ 2, 13, 23, 1662803 }); if (n < 2'152'302'898'747) return tests({ 2, 3, 5, 7, 11 }); if (n < 3'474'749'660'383) return tests({ 2, 3, 5, 7, 11, 13 }); if (n < 341'550'071'728'321) return tests({ 2, 3, 5, 7, 11, 13, 17 }); if (n < 3'825'123'056'546'413'051) return tests({ 2, 3, 5, 7, 11, 13, 17, 19, 23 }); if (ull(n) <= 18'446'744'073'709'551'615ULL) return tests({ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }); // 18'446'744'073'709'551'616 は 2^64 であり、これ以上の数は 64 ビット整数型では表現できない // TODO: 多倍長整数を使う場合は if を追加する // TODO: C++23 以降なら __builtin_unreachable() -> std::unreachable() に変更可能 __builtin_unreachable(); } } // namespace math } // namespace asalib namespace asalib { namespace math { template constexpr vector> pollards_rho(T n) { if (n < 2) [[unlikely]] return {}; vector> res(0); // ある程度小さい素因数については前もって素因数分解しておく for (T i = 2; i * i <= min((T) 10000, n); ++i) { if (n % i == 0) { T e = 0; while (n % i == 0) n /= i, ++e; res.push_back({ i, e }); } } if (n == 1) [[unlikely]] return res; // ここからメイン static_assert(sizeof(T) == 4 || sizeof(T) == 8, "T must be 32-bit or 64-bit integer type"); constexpr bool is_64bit = sizeof(T) == 8; auto f = [&](T x, T s) -> T { if constexpr (is_64bit) return ((__uint128_t) x * x + s) % n; else return ((unsigned long long) x * x + s) % n; }; function rho = [&](T& n, T cnt) { if (n == 1) [[unlikely]] return; if (miller_rabin_test(n)) { res.push_back({ n, cnt }); n = 1; return; } T s = 0; while (true) { T x = ++s, y = f(x, s); while (true) { T p = gcd(y - x + n, n); if (p == 0 || p == n) break; // 失敗、 seed 変えてやり直し if (p != 1) { assert(n % p == 0); T e = 0; while (n % p == 0) n /= p, ++e; rho(p, cnt * e); if (n > 1) rho(n, cnt); return; } x = f(x, s), y = f(f(y, s), s); } } }; while (n > 1) rho(n, 1); sort(res.begin(), res.end()); return res; } } // namespace math } // namespace asalib int main() { LL(N); auto pf = asalib::math::pollards_rho(N); //素因数分解 //分割数 const int maxi = 100; vvl dp(maxi+1,vl(maxi+1,0)); dp[0][0] = 1; rep(i,maxi) rep(j,maxi) { dp[i+1][j+1] += dp[i][j]; if(i+j<=maxi) dp[i+j][j] += dp[i][j]; } rep(i,maxi+1) rep(j,maxi) dp[i][j+1] += dp[i][j]; ll ema = -1; for(auto [p,e] : pf) chmax(ema, e); //各素因数(p,e)に対してdp[e][*]を使用できる ll ans = 0; for(int length = 1;length <= ema; length++) { //length以下をとる - length-1以下をとる ll r = 1, l = 1; for(auto [p,e] : pf) { r *= dp[e][length]; l *= dp[e][length-1]; } ans += r - l; } out(ans); }