#include <cstdio>
#include <cassert>
#include <cmath>
#include <functional>
#include <stack>
using u64 = unsigned long long;
using u32 = unsigned;
struct u128 {
u128() : l(0), h(0) {}
u128(u64 l) : l(l), h(0) {}
u128(u64 l, u64 h) : l(l), h(h) {}
static u128 mul64(u64 a, u64 b) {
u32 a_hi = a >> 32, a_lo = u32(a);
u32 b_hi = b >> 32, b_lo = u32(b);
u64 p0 = u64(a_lo) * b_lo;
u64 p10 = u64(a_hi) * b_lo + (p0 >> 32);
u64 p11 = u64(a_lo) * b_hi + p10;
u64 p2 = (u64(p11 < p10) << 32) + u64(a_hi) * b_hi + (p11 >> 32);
return u128(u32(p0) | (p11 << 32), p2);
}
static void divmod(u128 a, u32 d, u128& q, u32& r) {
u32 a3 = a.h >> 32, a2 = a.h;
u32 a1 = a.l >> 32, a0 = a.l;
u64 t = a3;
u32 q3 = t / d; t = ((t % d) << 32) | a2;
u32 q2 = t / d; t = ((t % d) << 32) | a1;
u32 q1 = t / d; t = ((t % d) << 32) | a0;
u32 q0 = t / d; r = t % d;
q = u128(q0 | (u64(q1) << 32), q2 | (u64(q3) << 32));
}
bool is_zero() const {
return l == 0 && h == 0;
}
bool operator >= (const u128& rhs) const {
return h > rhs.h || (h == rhs.h && l >= rhs.l);
}
u128& operator += (const u64 rhs) {
u64 old_l = l;
l += rhs;
h += (l < old_l);
return *this;
}
u128& operator += (const u128& rhs) {
u64 old_l = l;
l += rhs.l;
h += (l < old_l) + rhs.h;
return *this;
}
u128& operator -= (const u128& rhs) {
u64 old_l = l;
l -= rhs.l;
h -= (l > old_l) + rhs.h;
return *this;
}
u128 operator + (const u64 rhs) const {
return u128(*this) += rhs;
}
u128 operator + (const u128& rhs) const {
return u128(*this) += rhs;
}
u128 operator - (const u128& rhs) const {
return u128(*this) -= rhs;
}
std::string to_string() const {
static const u32 ten9 = u32(1e9);
if (is_zero()) {
return "0";
}
char str[41];
int i = 0;
u128 n = *this;
u32 r;
while (1) {
divmod(n, ten9, n, r);
if (n.is_zero()) {
while (r > 0) str[i++] = r % 10, r /= 10;
break;
} else {
for (int j = 0; j < 9; ++j) str[i++] = r % 10, r /= 10;
}
}
std::string ret;
while (i) ret += '0' + str[--i];
return ret;
}
u64 l, h;
};
u32 isqrt(u64 n) {
if (n >= u64(UINT32_MAX) * UINT32_MAX) {
return UINT32_MAX;
} else {
u32 ret = sqrtl(n);
assert(u64(ret) * ret <= n);
assert(u64(ret + 1) * (ret + 1) > n);
return ret;
}
}
inline u64 div64_32(u64 a, u32 b) {
u32 r, ql, qh;
u32 al = a, ah = a >> 32;
qh = ah / b; ah %= b;
__asm__ (
"divl %4\n\t"
: "=a"(ql), "=d"(r)
: "0"(al), "1"(ah), "rm"(b)
);
return (u64(qh) << 32) | ql;
}
u128 sigma0_sum(u64 N) {
// 1 から N までの約数の個数の総和を返す。
// 計算量: O(n^(1/3+))
const u32 v = isqrt(N);
const u32 w = pow(N, 0.35);
u64 x = N / v;
u32 y = N / x + 1;
std::stack< std::pair<u32, u32> > stac;
stac.emplace(1, 0);
stac.emplace(1, 1);
auto outside = [N] (u64 x, u32 y) {
return x * y > N;
};
auto cut_off = [N] (u64 x, u32 ldx, u32 ldy) {
return u128::mul64(x, x * ldy) >= u128::mul64(N, ldx);
};
u128 ret = 0;
while (1) {
u32 ldx, ldy;
std::tie(ldx, ldy) = stac.top(); stac.pop();
while (outside(x + ldx, y - ldy)) {
ret += x * ldy + u64(ldy + 1) * (ldx - 1) / 2;
x += ldx; y -= ldy;
}
if (y <= w) {
break;
}
u32 udx = ldx, udy = ldy;
while (1) {
std::tie(ldx, ldy) = stac.top();
if (outside(x + ldx, y - ldy)) break;
udx = ldx, udy = ldy;
stac.pop();
}
while (1) {
u32 mdx = ldx + udx;
u32 mdy = ldy + udy;
if (outside(x + mdx, y - mdy)) {
ldx = mdx, ldy = mdy;
stac.emplace(ldx, ldy);
} else {
if (cut_off(x + mdx, ldx, ldy)) {
break;
}
udx = mdx, udy = mdy;
}
}
}
for (u32 i = y - 1; i > 0; --i) {
ret += div64_32(N, i);
}
ret = ret + ret - u64(v) * v;
return ret;
}
u128 spiral_walk(u64 N) {
/*
横 w, 縦 h の格子状の道における距離は (w + 1) * (h + 1) - 1 となる。
したがって、正の整数 n に対して F(n) = (n + 1 の約数の個数) - 2 となる。
これを 1 から n まで足し合わせたものが G(n) であるから、
以下のような式で書くことができる。
*/
return sigma0_sum(N + 1) - 1 - N - N;
}
int main() {
u64 N;
while (~scanf("%llu", &N)) {
// G(1e19) = 419035480966899467511 ; 0.59 秒
// G(18446744065119617022) = 784279019989592462219 ; 0.71 秒
assert(1 <= N && N <= 0xFFFFFFFDFFFFFFFFull - 1);
const u128 ans = spiral_walk(N);
puts(ans.to_string().c_str());
}
}