#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using Int = long long; template ostream &operator<<(ostream &os, const pair &a) { return os << "(" << a.first << ", " << a.second << ")"; }; template ostream &operator<<(ostream &os, const vector &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; } template void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; } template bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; } template bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; } #define COLOR(s) ("\x1b[" s "m") // cannot use count // no move constructor (==> use pointer for merge tech) // unordered_set by value: __gnu_pbds::null_type // no erase(iterator) #include using __gnu_pbds::gp_hash_table; // https://codeforces.com/blog/entry/62393 #include struct Hash { static uint64_t splitmix64(uint64_t x) { // http://xorshift.di.unimi.it/splitmix64.c x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } size_t operator()(const pair &a) const { return operator()((uint64_t)a.first << 32 | a.second); } }; template using Set = gp_hash_table; template using Map = gp_hash_table; inline long long divide(long long a, int b) { return a / b; } inline long long divide(long long a, long long b) { return a / b; } // quo[i - 1] < x <= quo[i] <=> floor(N/x) = quo[len - i] (1 <= i <= len - 1) struct Quotients { long long N; int N2; int len; Quotients(long long N_ = 0) : N(N_) { N2 = sqrt(static_cast(N)); len = 2 * N2 + ((static_cast(N2) * (N2 + 1) <= N) ? 1 : 0); } long long operator[](int i) const { return (i <= N2) ? i : divide(N, len - i); } int indexOf(long long x) const { return (x <= N2) ? x : (len - divide(N, x)); } friend std::ostream &operator<<(std::ostream &os, const Quotients &quo) { os << "["; for (int i = 0; i < quo.len; ++i) { if (i > 0) os << ", "; os << quo[i]; } os << "]"; return os; } }; /* k (m^2-n^2, 2mn, m^2+n^2) \sum[k,m,n] [gcd(m, n) = 1] [m != n (mod 2)] [1 <= n < m] [2km(m+n) <= N] = \sum[k,m,n] (\sum[d] [d | m] [d | n] \mu(d)) [m != n (mod 2)] [1 <= n < m] [km(m+n) <= N/2] = \sum[d] [2 !| d] \mu(d) \sum[k,m,n] [m != n (mod 2)] [1 <= n < m] [km(m+n) <= N/2/d^2] */ constexpr int K = 100'000'000; Int small[K + 1]; void init() { for (Int m = 1; m * (m + 1) <= K; ++m) { for (Int n = (m & 1) + 1; m * (m + n) <= K && n < m; n += 2) { ++small[m * (m + n)]; } } for (Int k = 1; k <= K; ++k) small[k] += small[k - 1]; } Map cache1; Int solve1(Int N) { if (N <= K) return small[N]; auto it = cache1.find(N); if (it != cache1.end()) return it->second; const Quotients quo(N); Int ret = 0; for (Int m = 1; m * (m + 1) <= N; ++m) { ret += ((min(N / m, 2 * m - 1) + 1) / 2 - (m + 1) / 2); } return cache1[N] = ret; } Map cache; Int solve(Int N) { auto it = cache.find(N); if (it != cache.end()) return it->second; const Quotients quo(N); Int ret = 0; for (int i = 1; i < quo.len; ++i) { ret += (quo[i] - quo[i - 1]) * solve1(quo[quo.len - i]); } return cache[N] = ret; } constexpr int LIM = 1'000'010; int lpf[LIM], moe[LIM]; int main() { for (int p = 2; p < LIM; ++p) lpf[p] = p; for (int n = 1; n < LIM; ++n) moe[n] = 1; for (int p = 2; p < LIM; ++p) if (lpf[p] == p) { for (int n = p; n < LIM; n += p) { chmin(lpf[n], p); moe[n] = -moe[n]; } } for (int d = 2; d*d < LIM; ++d) if (moe[d]) { for (int n = d*d; n < LIM; n += d*d) moe[n] = 0; } // pv(moe,moe+31); init(); Int N; for (; ~scanf("%lld", &N); ) { N /= 2; Int ans = 0; for (Int d = 1; d*d <= N; d += 2) if (moe[d]) { ans += moe[d] * solve(N / (d*d)); } printf("%lld\n", ans); } return 0; }