ll icbrtll(ll n) { ll x = (ll)llround(powl((longdouble)n, 1.0L / 3.0L)); while ((x + 1) * (x + 1) * (x + 1) <= n) ++x; while (x * x * x > n) --x; return x; }
// pack key for memo: (x << 17) | m, since m <= 1e5 < 2^17 and x <= 1e10 < 2^34 ll pack_key(ll x, int m) { return (ll(x) << 17) | (ll)m; }
// ---------- globals ---------- ll GN; // N in problem int LIM; // floor(sqrt(N))
vector<int> mu; // mu[1..LIM] vector<int> mu_pref; // prefix sum of mu vector<char> is_sqfree; // squarefree up to LIM vector<int> sf_pref; // Q_small prefix counts including 1 vector<int> sq_list; // squarefree numbers >=2 up to LIM vector<ll> sq_Qm1_pref; // prefix sum over squarefree f: Q(f-1) for f in sq_list (small only) unordered_map<ll, ll> Q_cache; // Q(x) for x > LIM unordered_map<ll, ll> G_cache; // G(x,m)
// ---------- build mobius up to LIM ---------- voidbuild_mobius(int n) { mu.assign(n + 1, 0); vector<int> primes; vector<int> spf(n + 1, 0); mu[1] = 1; for (int i = 2; i <= n; ++i) { if (spf[i] == 0) { spf[i] = i; primes.push_back(i); mu[i] = -1; } for (int p : primes) { ll v = 1LL * i * p; if (v > n) break; spf[(int)v] = p; if (i % p == 0) { mu[(int)v] = 0; break; } mu[(int)v] = -mu[i]; } } mu_pref.assign(n + 1, 0); int s = 0; for (int i = 1; i <= n; ++i) { s += mu[i]; mu_pref[i] = s; } }
// ---------- build squarefree prefix up to LIM ---------- voidbuild_squarefree_prefix(int n) { is_sqfree.assign(n + 1, true); is_sqfree[0] = false; for (int p = 2; 1LL * p * p <= n; ++p) { int pp = p * p; for (int k = pp; k <= n; k += pp) is_sqfree[k] = false; } sf_pref.assign(n + 1, 0); int s = 0; for (int i = 0; i <= n; ++i) { if (is_sqfree[i]) ++s; sf_pref[i] = s; } sq_list.clear(); for (int i = 2; i <= n; ++i) if (is_sqfree[i]) sq_list.push_back(i);
sq_Qm1_pref.assign(sq_list.size() + 1, 0); for (size_t i = 0; i < sq_list.size(); ++i) { int f = sq_list[i]; // for f <= LIM, Q(f-1) = sf_pref[f-1] sq_Qm1_pref[i + 1] = sq_Qm1_pref[i] + sf_pref[f - 1]; } }
// ---------- Q(x): count squarefree <= x INCLUDING 1 ---------- ll Q(ll x) { if (x <= LIM) return sf_pref[(int)x]; auto it = Q_cache.find(x); if (it != Q_cache.end()) return it->second;
ll res = 0; ll k = 1; while (k * k <= x) { ll v = x / (k * k); ll kmax = int_square(x / v); res += v * ((ll)mu_pref[(int)kmax] - (ll)mu_pref[(int)k - 1]); k = kmax + 1; } Q_cache.emplace(x, res); return res; }
intcount_sqfree_interval_small(int a, int b) { if (a > b) return0; return sf_pref[b] - sf_pref[a - 1]; }
ll sum_Qm1_interval_small(int a, int b) { if (a > b) return0; auto l = lower_bound(sq_list.begin(), sq_list.end(), a) - sq_list.begin(); auto r = upper_bound(sq_list.begin(), sq_list.end(), b) - sq_list.begin(); return sq_Qm1_pref[r] - sq_Qm1_pref[l]; }
// ---------- G(x,m): # nondecreasing sequences of squarefree factors >=m, product<=x, allowing empty ---------- ll G(ll x, int m) { ll key = pack_key(x, m); auto it = G_cache.find(key); if (it != G_cache.end()) return it->second;
ll lim = int_square(x); ll res;
if (m > lim) { res = 1 + (Q(x) - Q((ll)m - 1)); G_cache.emplace(key, res); return res; }
// empty + choose a single factor > sqrt(x) res = 1 + (Q(x) - Q(lim));
ll cbr = icbrtll(x); int upper = (int)min(lim, cbr);
// recursive part: m <= f <= upper (squarefree) if (m <= upper) { auto li = lower_bound(sq_list.begin(), sq_list.end(), m) - sq_list.begin(); auto ri = upper_bound(sq_list.begin(), sq_list.end(), upper) - sq_list.begin(); for (size_t idx = li; idx < ri; ++idx) { int f = sq_list[idx]; res += G(x / f, f); } }
// compressed part: upper < f <= lim (here lim <= LIM always) int A = max(m, upper + 1); int B = (int)lim; if (A <= B) { int cnt = count_sqfree_interval_small(A, B); ll sum_qm1 = sum_Qm1_interval_small(A, B);
// sum_{squarefree f in [A,B]} Q(x/f), grouped by q = floor(x/f) ll sum_qq = 0; int t = A; while (t <= B) { ll q = x / t; int tmax = (int)min<ll>(B, x / q); int c = count_sqfree_interval_small(t, tmax); if (c) sum_qq += Q(q) * (ll)c; t = tmax + 1; }