#include "bits/stdc++.h"
using namespace std;
using ll = long long;
ll count_primes(ll n) {
vector<ll> v;
for (ll k = 1; k * k <= n; ++k) {
v.push_back(n / k);
v.push_back(k);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
// return i such that v[i] = x
// since v[i] = i + 1 for i <= sqrt(n) and v[v.size() - i] = n / i for i <= sqrt(n),
// we can calculate index in O(1)
ll sq = sqrt(n);
auto geti = [&](ll x) {
if (x <= sq) return (int)x - 1;
else return (int)(v.size() - (n / x));
};
vector<ll> dp(v.size());
// S(n, 0) = n
for (int i = 0; i < v.size(); ++i)
dp[i] = v[i];
int a = 0;
for (ll p = 2; p * p <= n; ++p) {
// this condition is true for primes
if (dp[geti(p)] != dp[geti(p - 1)]) {
++a;
for (int i = (int)v.size() - 1; i >= 0; --i) {
if (v[i] < p * p) break;
dp[i] -= dp[geti(v[i] / p)] - a;
}
}
}
return dp[geti(n)] - 1;
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
vector<ll> ns = {(ll)1e10, (ll)1e11, (ll)1e12, (ll)1e13};
for (ll n : ns) {
auto start_time = clock();
cout << "n = " << (double)n << endl;
ll res = count_primes(n);
cout << "result: " << res << endl;
cout << "time: " << (double)(clock() - start_time) / CLOCKS_PER_SEC << "s" << endl;
cout << endl;
}
return 0;
}
I2luY2x1ZGUgImJpdHMvc3RkYysrLmgiCgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdXNpbmcgbGwgPSBsb25nIGxvbmc7CmxsIGNvdW50X3ByaW1lcyhsbCBuKSB7CiAgICB2ZWN0b3I8bGw+IHY7CiAgICBmb3IgKGxsIGsgPSAxOyBrICogayA8PSBuOyArK2spIHsKICAgICAgICB2LnB1c2hfYmFjayhuIC8gayk7CiAgICAgICAgdi5wdXNoX2JhY2soayk7CiAgICB9CiAgICBzb3J0KHYuYmVnaW4oKSwgdi5lbmQoKSk7CiAgICB2LmVyYXNlKHVuaXF1ZSh2LmJlZ2luKCksIHYuZW5kKCkpLCB2LmVuZCgpKTsKCiAgICAvLyByZXR1cm4gaSBzdWNoIHRoYXQgdltpXSA9IHgKICAgIC8vIHNpbmNlIHZbaV0gPSBpICsgMSBmb3IgaSA8PSBzcXJ0KG4pIGFuZCB2W3Yuc2l6ZSgpIC0gaV0gPSBuIC8gaSBmb3IgaSA8PSBzcXJ0KG4pLAogICAgLy8gd2UgY2FuIGNhbGN1bGF0ZSBpbmRleCBpbiBPKDEpCiAgICBsbCBzcSA9IHNxcnQobik7CiAgICBhdXRvIGdldGkgPSBbJl0obGwgeCkgewogICAgICAgIGlmICh4IDw9IHNxKSByZXR1cm4gKGludCl4IC0gMTsKICAgICAgICBlbHNlICAgICAgICAgcmV0dXJuIChpbnQpKHYuc2l6ZSgpIC0gKG4gLyB4KSk7CiAgICB9OwoKICAgIHZlY3RvcjxsbD4gZHAodi5zaXplKCkpOwoKICAgIC8vIFMobiwgMCkgPSBuCiAgICBmb3IgKGludCBpID0gMDsgaSA8IHYuc2l6ZSgpOyArK2kpCiAgICAgICAgZHBbaV0gPSB2W2ldOwoKICAgIGludCBhID0gMDsKICAgIGZvciAobGwgcCA9IDI7IHAgKiBwIDw9IG47ICsrcCkgewogICAgICAgIC8vIHRoaXMgY29uZGl0aW9uIGlzIHRydWUgZm9yIHByaW1lcwogICAgICAgIGlmIChkcFtnZXRpKHApXSAhPSBkcFtnZXRpKHAgLSAxKV0pIHsKICAgICAgICAgICAgKythOwogICAgICAgICAgICBmb3IgKGludCBpID0gKGludCl2LnNpemUoKSAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgICAgICAgICBpZiAodltpXSA8IHAgKiBwKSBicmVhazsKICAgICAgICAgICAgICAgIGRwW2ldIC09IGRwW2dldGkodltpXSAvIHApXSAtIGE7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIGRwW2dldGkobildIC0gMTsKfQoKaW50IG1haW4oKSB7CiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsgY2luLnRpZShOVUxMKTsgY291dC50aWUoTlVMTCk7CgogICAgdmVjdG9yPGxsPiBucyA9IHsobGwpMWUxMCwgKGxsKTFlMTEsIChsbCkxZTEyLCAobGwpMWUxM307CiAgICBmb3IgKGxsIG4gOiBucykgewogICAgICAgIGF1dG8gc3RhcnRfdGltZSA9IGNsb2NrKCk7CiAgICAgICAgY291dCA8PCAibiA9ICIgPDwgKGRvdWJsZSluIDw8IGVuZGw7CiAgICAgICAgbGwgcmVzID0gY291bnRfcHJpbWVzKG4pOwogICAgICAgIGNvdXQgPDwgInJlc3VsdDogIiA8PCByZXMgPDwgZW5kbDsKICAgICAgICBjb3V0IDw8ICJ0aW1lOiAiIDw8IChkb3VibGUpKGNsb2NrKCkgLSBzdGFydF90aW1lKSAvIENMT0NLU19QRVJfU0VDIDw8ICJzIiA8PCBlbmRsOwogICAgICAgIGNvdXQgPDwgZW5kbDsKICAgIH0KCiAgICByZXR1cm4gMDsKfQo=