#pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include #include #define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++) using namespace atcoder; using namespace std; typedef long long ll; struct LucyDP { ll prime_count; // 素数の個数 ll prime_sum; // 素数の和 ll min_prime_element_sum; // 最小素因数の和 map prime_factor_count; // 素因数の個数 LucyDP() : prime_count(0), prime_sum(0), min_prime_element_sum(0) {} void compute(ll n) { ll r = (ll)floor(sqrt(n)); vector V; for (ll i = 1; i <= r; i++) { V.push_back(n / i); } for (ll i = V.back() - 1; i >= 1; i--) { V.push_back(i); } unordered_map idx; idx.reserve(V.size() * 2); for (int i = 0; i < (int)V.size(); i++) { idx[V[i]] = i; } vector S_arr(V.size()), C_arr(V.size()); for (int i = 0; i < (int)V.size(); i++) { ll v = V[i]; S_arr[i] = v * (v + 1) / 2 - 1; C_arr[i] = v - 1; } ll lpsum = 0; for (ll p = 2; p <= r; p++) { int pos_p = idx[p]; int pos_pm1 = idx[p - 1]; if (S_arr[pos_p] == S_arr[pos_pm1]) continue; ll sp = S_arr[pos_pm1]; ll cp = C_arr[pos_pm1]; for (int i = 0; i < (int)V.size(); i++) { ll v = V[i]; if (v < p * p) break; int pos_v_div = idx[v / p]; S_arr[i] -= p * (S_arr[pos_v_div] - sp); C_arr[i] -= (C_arr[pos_v_div] - cp); if (v == n) { lpsum += p * (C_arr[pos_v_div] - cp); } } } int pos_n = idx[n]; prime_count = C_arr[pos_n]; prime_sum = S_arr[pos_n]; min_prime_element_sum = lpsum + S_arr[pos_n]; } void compute2(ll n) { ll r = (ll)floor(sqrt(n)); vector V; for (ll i = 1; i <= r; i++) { V.push_back(n / i); } for (ll i = V.back() - 1; i >= 1; i--) { V.push_back(i); } unordered_map idx; idx.reserve(V.size() * 2); for (int i = 0; i < (int)V.size(); i++) { idx[V[i]] = i; } vector S_arr(V.size()), C_arr(V.size()); for (int i = 0; i < (int)V.size(); i++) { ll v = V[i]; S_arr[i] = v * (v + 1) / 2 - 1; C_arr[i] = v - 1; } ll lpsum = 0; for (ll p = 2; p <= r; p++) { int pos_p = idx[p]; int pos_pm1 = idx[p - 1]; if (S_arr[pos_p] == S_arr[pos_pm1]) continue; ll sp = S_arr[pos_pm1]; ll cp = C_arr[pos_pm1]; for (int i = 0; i < (int)V.size(); i++) { ll v = V[i]; if (v < p * p) break; int pos_v_div = idx[v / p]; S_arr[i] -= p * (S_arr[pos_v_div] - sp); C_arr[i] -= (C_arr[pos_v_div] - cp); if (v == n) { lpsum += p * (C_arr[pos_v_div] - cp); } } } int pos_n = idx[n]; prime_count = C_arr[pos_n]; prime_sum = S_arr[pos_n]; min_prime_element_sum = lpsum + S_arr[pos_n]; vector isPrime(n + 1, true); isPrime[0] = isPrime[1] = false; for (ll i = 2; i * i <= n; i++) { if (isPrime[i]) { for (ll j = i * i; j <= n; j += i) isPrime[j] = false; } } for (ll p = 2; p <= n; p++) { if (!isPrime[p]) continue; ll cnt = 0; for (ll q = p; q <= n; q *= p) { cnt += n / q; } prime_factor_count[p] = cnt; } } }; ll sqrt_ll(ll n) { // return floor(√n) auto check = [&](ll mid) { if (mid * mid <= n) return true; else return false; }; auto binary = [&]() { ll L = 0, R = 3000000010; ll mid = (L + R) / 2; while (R - L > 1) { if (check(mid)) L = mid; else R = mid; mid = (L + R) / 2; } return L; }; ll ret = binary(); return ret; } using mint = atcoder::modint1000000007; vector make_primes(ll n) { vector prime; vector is_prime(n + 1, true); is_prime[0] = is_prime[1] = false; for (ll i = 2; i <= n; i++) { if (is_prime[i]) { prime.push_back(i); for (ll j = i * 2; j <= n; j += i) { is_prime[j] = false; } } } return prime; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); ll n; cin >> n; ll m = sqrt_ll(n); LucyDP lucy; lucy.compute(n); mint ans = 1; for (auto [p, cnt] : lucy.prime_factor_count) { ans *= (cnt + 1); } cout << ans.val() << endl; }