#pragma GCC optimize(2)
#include <iostream>
#include <vector>
#include <cmath>
#include <utility>
#include <functional>
#include <algorithm>
#include <ctime>
#include <bitset>
using namespace std;
using u32 = unsigned int;
using u64 = unsigned long long;
using i64 = long long;
vector<int> pi, pos;
vector<u32> phi, primes;
const int MAX = 8000000;
static bitset<MAX> is_prime;
void sieve(int v) {
pi.resize(v + 1);
phi.resize(v + 1);
pos.resize(v + 1);
primes.push_back(1);
phi[1] = 1;
for (int i = 2, t; i <= v; ++i) {
if (!phi[i]) pos[i] = primes.size(), primes.push_back(i), phi[i] = i - 1;
for (int j = 1; j <= pos[i] && (t = i * primes[j]) <= v; ++j) {
pos[t] = j;
if (j == pos[i]) {
phi[t] = phi[i] * primes[j];
break;
}
else
phi[t] = phi[i] * (primes[j] - 1);
}
}
for (int id = 1; id < primes.size(); ++id) pi[primes[id]] = 1;
for (int i = 1; i <= v; ++i) pi[i] += pi[i - 1];
}
u32 solve(const u64 N) {
const int v = sqrt(N + 0.5);
const int n_6 = pow(N + 0.5, 1.0 / 6) * 0.4;
const int n_4 = sqrt(v + 0.5);
const int K = n_6 * v;
const int B = N / K;
const int limit = min<i64>(cbrt(N) * log(N), v);
const int B2 = N / limit;
clock_t clk = clock();
sieve(v);
vector<u32> s0(v + 1), s1(v + 1), l0(v + 1), l1(v + 1);
const auto divide = [](u64 n, u64 d) -> u64 {return double(n) / d; };
for (int i = 1; i <= v; ++i) s0[i] = i, s1[i] = u64(i) * (i + 1) / 2;
for (int i = 1; i <= v; ++i) l0[i] = N / i, l1[i] = (N / i) * (N / i + 1) / 2;
for (int id = 1; id <= pi[n_6]; ++id) {
const u32 p = primes[id], t = v / p;
const i64 M = N / p;
for (int i = 1; i <= t; ++i)
l0[i] -= l0[i * p], l1[i] -= l1[i * p] * p;
for (int i = t + 1; i <= v; ++i)
l0[i] -= s0[divide(M, i)], l1[i] -= s1[divide(M, i)] * p;
for (int i = v, j = t; j; --j)
for (int e = j * p; i >= e; --i)
s0[i] -= s0[j], s1[i] -= s1[j] * p;
}
vector<u32> sf(v + 1), lf(v + 1);
function <void(u64, int, u32)> dfs = [&](u64 n, int beg, u32 coeff) -> void {
if (n <= v) sf[n] += coeff - n + 1;
else lf[divide(N, n)] += coeff - n + 1;
int m = K / n;
for (int i = beg + 1; i <= pi[v]; ++i) {
if (primes[i] > m) break;
u64 q = 1;
for (; q * primes[i] <= m; q *= primes[i])
dfs(n * q * primes[i], i, coeff * q * (primes[i] - 1));
}
};
dfs(1, pi[n_6], 1);
for (int i = 1; i <= v; ++i) sf[i] += sf[i - 1];
lf[v] += sf[v];
for (int i = v - 1; i > B; --i) lf[i] += lf[i + 1];
for (int i = 1; i <= v; ++i) sf[i] += s1[i] - s0[i], lf[i] += l1[i] - l0[i];
vector<int> roughs;
for (int i = n_6 + 1; i <= v; ++i)
if (s0[i] != s0[i - 1]) roughs.push_back(i);
roughs.push_back(v + 1);
for (int i = B; i >= 1; --i) {
const u64 m = divide(N, i);
const int u = sqrt(m + 0.5), t = divide(v, i);
int k = 0, l;
lf[i] = l1[i] - l0[i] + s0[u] * sf[u];
for (; (l = roughs[k]) <= t; ++k)
lf[i] -= lf[i * l] + (sf[l] - sf[l - 1]) * l0[i * l];
for (; (l = roughs[k]) <= u; ++k)
lf[i] -= sf[divide(m, l)] + (sf[l] - sf[l - 1]) * s0[divide(m, l)];
}
fprintf(stderr, "sieve done %lf\n", double(clock() - clk) / 1000);
clk = clock();
u32 ans = 0;
const auto ff = [&](i64 n, int k) -> double {
double P = 1;
i64 x = 1;
while (k <= pi[v] && x * primes[k] <= n) {
x *= primes[k];
P = P * primes[k] / (primes[k] - 1);
++k;
}
return P;
};
vector<u32> f(pi[v] + 1);
for (int id = 1; id <= pi[v]; ++id) f[id] += f[id - 1] + primes[id] - 1;
int lim = 0;
vector<vector<pair<u64, u32>>> d1(pi[v] + 1);
auto dfs1 = [&](const auto& self, u64 d, int beg, u64 coeff) -> void {
u64 m = divide(N, d);
double g = d * 1. / coeff;
if (int(g) == int(g * ff(m, beg + 1))) return;
for (int i = beg + 1; i <= pi[v]; ++i) {
u64 pr = primes[i];
if (pr * pr > m) break;
double g1 = g * pr / (pr - 1);
if (int(g1) != int(g))
d1[i].push_back(make_pair(d, coeff)), d* pr <= limit && (lim = max(lim, i));
u64 q = 1;
for (; q * pr <= m; q *= pr)
self(self, d * q * pr, i, coeff * q * (pr - 1));
}
int left = pi[min<i64>(min<i64>(v, (int(g) + 1) * 1. / (int(g) + 1 - g)), m)];
int right = max(beg, pi[sqrt(m)]);
if (left > right) ans += coeff * (f[left] - f[right]);
};
dfs1(dfs1, 1, 0, 1);
fprintf(stderr, "dfs done %lf\n", double(clock() - clk) / 1000);
clk = clock();
for (int i = 1; i <= v; ++i) l0[i] = lf[i], s0[i] = sf[i];
for (int id = pi[n_6]; id; --id) {
const u32 p = primes[id], t = v / p;
const u64 M = N / p;
if (id <= lim) {
for (auto d : d1[id])
ans -= d.second * (d.first <= v ? l0[d.first] : s0[divide(N, d.first)]);
}
for (int i = 1; i <= t; ++i) l0[i] -= l0[i * p];
for (int i = t + 1; i <= v; ++i) l0[i] -= s0[divide(M, i)];
for (int i = v, j = t; j; --j)
for (int c = j * p; i >= c; --i) s0[i] -= s0[j];
for (int j = 1, i = p; j <= t; ++j) {
const u32 c = p * s0[j];
for (int e = min<u32>(v + 1, i + p); i < e; ++i) s0[i] += c;
}
for (int i = v; i > t; --i) l0[i] += p * s0[divide(M, i)];
for (int i = t; i; --i) l0[i] += p * l0[i * p];
if (id <= lim) {
for (auto d : d1[id])
ans += d.second * (d.first <= v ? l0[d.first] : s0[divide(N, d.first)]);
}
}
ans += l0[1];
for (int id = pi[n_6] + 1; id <= lim; ++id) {
const u32 p = primes[id], t = v / p;
const u64 M = N / p;
for (auto d : d1[id])
ans += d.second * (d.first <= v ? lf[d.first] : sf[divide(N, d.first)]);
for (int i = 1; i <= t; ++i) lf[i] -= p * lf[i * p];
for (int i = t + 1; i <= v; ++i) lf[i] -= p * sf[divide(M, i)];
for (int i = v, j = t; j; --j)
for (int c = j * p; i >= c; --i) sf[i] -= p * sf[j];
for (int j = 1, i = p; j <= t; ++j)
for (int e = min<int>(v + 1, i + p); i < e; ++i) sf[i] += sf[j];
for (int i = v; i > t; --i) lf[i] += sf[divide(M, i)];
for (int i = t; i; --i) lf[i] += lf[i * p];
for (auto d : d1[id])
ans -= d.second * (d.first <= v ? lf[d.first] : sf[divide(N, d.first)]);
}
fprintf(stderr, "dp done %lf\n", double(clock() - clk) / 1000);
clk = clock();
vector<u32> bit(B2 + 1);
const auto add = [&](int x, const u32 cnt) -> void {
while (x <= B2) bit[x] += cnt, x += x & -x;
};
const auto query = [&](int x) -> u32 {
u32 ans = 0;
while (x) ans += bit[x], x ^= x & -x;
return ans;
};
add(1, 1);
int v1 = sqrt(B2), v0 = (B2 - 1) / 2;
for (int id = 2, p = 3; p <= v1; p = primes[++id])
for (int j = p * p >> 1; j <= v0; j += p)
is_prime[j] = true;
for (int i = (v + 1) / 2; i <= v0; ++i)
if (!is_prime[i])
add(2 * i + 1, 2 * i), primes.push_back(2 * i + 1);
function <void(u64, int, u32)> dfs2 = [&](u64 n, int id, u32 fn) {
add(n, fn);
const int m = B2 / n;
for (int i = id + 1; i < primes.size(); ++i) {
const int pr = primes[i];
if (pr > m) break;
u64 q = 1;
for (; q * pr <= m; q *= pr)
dfs2(n * q * pr, i, fn * q * (pr - 1));
}
};
for (int id = pi[v]; id > lim; --id) {
const u32 p = primes[id];
const u64 m = divide(N, p);
for (auto d : d1[id]) {
u32 n = m / d.first, phi0 = p - 1;
while (n) {
ans += phi0 * d.second * query(n);
n /= p;
phi0 *= p;
}
}
u64 q = 1;
while (p * q <= B2) {
dfs2(p * q, id, q * (p - 1));
q *= p;
}
}
fprintf(stderr, "bit done %lf\n", double(clock() - clk) / 1000);
return N * (N + 1) / 2 - ans;
}
signed main() {
u64 n;
cin >> n;
cout << solve(n);
return 0;
}