#include "bits/stdc++.h"
using namespace std;
using ll = long long;
struct _count_primes_struct_t_ {
vector<int> primes;
vector<int> mnprimes;
ll ans;
ll y;
vector<pair<pair<ll, int>, char>> queries;
ll count_primes(ll n) {
// this y is actually n/y
// also no logarithms, welcome to reality, this y is the best for n=10^12 or n=10^13
y = pow(n, 0.64);
if (n < 100) y = n;
// linear sieve
primes.clear();
mnprimes.assign(y + 1, -1);
ans = 0;
for (int i = 2; i <= y; ++i) {
if (mnprimes[i] == -1) {
mnprimes[i] = primes.size();
primes.push_back(i);
}
for (int k = 0; k < primes.size(); ++k) {
int j = primes[k];
if (i * j > y) break;
mnprimes[i * j] = k;
if (i % j == 0) break;
}
}
if (n < 100) return primes.size();
ll s = n / y;
for (int p : primes) {
if (p > s) break;
ans++;
}
// pi(n / y)
int ssz = ans;
// F with two pointers
int ptr = primes.size() - 1;
for (int i = ssz; i < primes.size(); ++i) {
while (ptr >= i && (ll)primes[i] * primes[ptr] > n)
--ptr;
if (ptr < i) break;
ans -= ptr - i + 1;
}
// phi, store all queries
phi(n, ssz - 1);
sort(queries.begin(), queries.end());
int ind = 2;
int sz = primes.size();
// the order in fenwick will be reversed, because prefix sum in a fenwick is just one query
fenwick fw(sz);
for (auto [na, sign] : queries) {
auto [n, a] = na;
while (ind <= n)
fw.add(sz - 1 - mnprimes[ind++], 1);
ans += (fw.ask(sz - a - 2) + 1) * sign;
}
queries.clear();
return ans - 1;
}
void phi(ll n, int a, int sign = 1) {
if (n == 0) return;
if (a == -1) {
ans += n * sign;
return;
}
if (n <= y) {
queries.emplace_back(make_pair(n, a), sign);
return;
}
phi(n, a - 1, sign);
phi(n / primes[a], a - 1, -sign);
}
struct fenwick {
vector<int> tree;
int n;
fenwick(int n = 0) : n(n) {
tree.assign(n, 0);
}
void add(int i, int k) {
for (; i < n; i = (i | (i + 1)))
tree[i] += k;
}
int ask(int r) {
int res = 0;
for (; r >= 0; r = (r & (r + 1)) - 1)
res += tree[r];
return res;
}
};
} _count_primes_struct_;
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_struct_t_().count_primes(n);
cout << "result: " << res << endl;
cout << "time: " << (double)(clock() - start_time) / CLOCKS_PER_SEC << "s" << endl;
cout << endl;
}
return 0;
}
I2luY2x1ZGUgImJpdHMvc3RkYysrLmgiCgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdXNpbmcgbGwgPSBsb25nIGxvbmc7CnN0cnVjdCBfY291bnRfcHJpbWVzX3N0cnVjdF90XyB7CiAgICB2ZWN0b3I8aW50PiBwcmltZXM7CiAgICB2ZWN0b3I8aW50PiBtbnByaW1lczsKICAgIGxsIGFuczsKICAgIGxsIHk7CiAgICB2ZWN0b3I8cGFpcjxwYWlyPGxsLCBpbnQ+LCBjaGFyPj4gcXVlcmllczsKCiAgICBsbCBjb3VudF9wcmltZXMobGwgbikgewogICAgICAgIC8vIHRoaXMgeSBpcyBhY3R1YWxseSBuL3kKICAgICAgICAvLyBhbHNvIG5vIGxvZ2FyaXRobXMsIHdlbGNvbWUgdG8gcmVhbGl0eSwgdGhpcyB5IGlzIHRoZSBiZXN0IGZvciBuPTEwXjEyIG9yIG49MTBeMTMKICAgICAgICB5ID0gcG93KG4sIDAuNjQpOwogICAgICAgIGlmIChuIDwgMTAwKSB5ID0gbjsKCiAgICAgICAgLy8gbGluZWFyIHNpZXZlCiAgICAgICAgcHJpbWVzLmNsZWFyKCk7CiAgICAgICAgbW5wcmltZXMuYXNzaWduKHkgKyAxLCAtMSk7CiAgICAgICAgYW5zID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMjsgaSA8PSB5OyArK2kpIHsKICAgICAgICAgICAgaWYgKG1ucHJpbWVzW2ldID09IC0xKSB7CiAgICAgICAgICAgICAgICBtbnByaW1lc1tpXSA9IHByaW1lcy5zaXplKCk7CiAgICAgICAgICAgICAgICBwcmltZXMucHVzaF9iYWNrKGkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAoaW50IGsgPSAwOyBrIDwgcHJpbWVzLnNpemUoKTsgKytrKSB7CiAgICAgICAgICAgICAgICBpbnQgaiA9IHByaW1lc1trXTsKICAgICAgICAgICAgICAgIGlmIChpICogaiA+IHkpIGJyZWFrOwogICAgICAgICAgICAgICAgbW5wcmltZXNbaSAqIGpdID0gazsKICAgICAgICAgICAgICAgIGlmIChpICUgaiA9PSAwKSBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAobiA8IDEwMCkgcmV0dXJuIHByaW1lcy5zaXplKCk7CiAgICAgICAgbGwgcyA9IG4gLyB5OwoKICAgICAgICBmb3IgKGludCBwIDogcHJpbWVzKSB7CiAgICAgICAgICAgIGlmIChwID4gcykgYnJlYWs7CiAgICAgICAgICAgIGFucysrOwogICAgICAgIH0KICAgICAgICAvLyBwaShuIC8geSkKICAgICAgICBpbnQgc3N6ID0gYW5zOwoKICAgICAgICAvLyBGIHdpdGggdHdvIHBvaW50ZXJzCiAgICAgICAgaW50IHB0ciA9IHByaW1lcy5zaXplKCkgLSAxOwogICAgICAgIGZvciAoaW50IGkgPSBzc3o7IGkgPCBwcmltZXMuc2l6ZSgpOyArK2kpIHsKICAgICAgICAgICAgd2hpbGUgKHB0ciA+PSBpICYmIChsbClwcmltZXNbaV0gKiBwcmltZXNbcHRyXSA+IG4pCiAgICAgICAgICAgICAgICAtLXB0cjsKICAgICAgICAgICAgaWYgKHB0ciA8IGkpIGJyZWFrOwogICAgICAgICAgICBhbnMgLT0gcHRyIC0gaSArIDE7CiAgICAgICAgfQoKICAgICAgICAvLyBwaGksIHN0b3JlIGFsbCBxdWVyaWVzIAogICAgICAgIHBoaShuLCBzc3ogLSAxKTsKCiAgICAgICAgc29ydChxdWVyaWVzLmJlZ2luKCksIHF1ZXJpZXMuZW5kKCkpOwogICAgICAgIGludCBpbmQgPSAyOwogICAgICAgIGludCBzeiA9IHByaW1lcy5zaXplKCk7CgogICAgICAgIC8vIHRoZSBvcmRlciBpbiBmZW53aWNrIHdpbGwgYmUgcmV2ZXJzZWQsIGJlY2F1c2UgcHJlZml4IHN1bSBpbiBhIGZlbndpY2sgaXMganVzdCBvbmUgcXVlcnkKICAgICAgICBmZW53aWNrIGZ3KHN6KTsKICAgICAgICBmb3IgKGF1dG8gW25hLCBzaWduXSA6IHF1ZXJpZXMpIHsKICAgICAgICAgICAgYXV0byBbbiwgYV0gPSBuYTsKICAgICAgICAgICAgd2hpbGUgKGluZCA8PSBuKQogICAgICAgICAgICAgICAgZncuYWRkKHN6IC0gMSAtIG1ucHJpbWVzW2luZCsrXSwgMSk7CiAgICAgICAgICAgIGFucyArPSAoZncuYXNrKHN6IC0gYSAtIDIpICsgMSkgKiBzaWduOwogICAgICAgIH0KICAgICAgICBxdWVyaWVzLmNsZWFyKCk7CiAgICAgICAgcmV0dXJuIGFucyAtIDE7CiAgICB9CgogICAgdm9pZCBwaGkobGwgbiwgaW50IGEsIGludCBzaWduID0gMSkgewogICAgICAgIGlmIChuID09IDApIHJldHVybjsKICAgICAgICBpZiAoYSA9PSAtMSkgewogICAgICAgICAgICBhbnMgKz0gbiAqIHNpZ247CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgaWYgKG4gPD0geSkgewogICAgICAgICAgICBxdWVyaWVzLmVtcGxhY2VfYmFjayhtYWtlX3BhaXIobiwgYSksIHNpZ24pOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHBoaShuLCBhIC0gMSwgc2lnbik7CiAgICAgICAgcGhpKG4gLyBwcmltZXNbYV0sIGEgLSAxLCAtc2lnbik7CiAgICB9CgogICAgc3RydWN0IGZlbndpY2sgewogICAgICAgIHZlY3RvcjxpbnQ+IHRyZWU7CiAgICAgICAgaW50IG47CgogICAgICAgIGZlbndpY2soaW50IG4gPSAwKSA6IG4obikgewogICAgICAgICAgICB0cmVlLmFzc2lnbihuLCAwKTsKICAgICAgICB9CgogICAgICAgIHZvaWQgYWRkKGludCBpLCBpbnQgaykgewogICAgICAgICAgICBmb3IgKDsgaSA8IG47IGkgPSAoaSB8IChpICsgMSkpKQogICAgICAgICAgICAgICAgdHJlZVtpXSArPSBrOwogICAgICAgIH0KCiAgICAgICAgaW50IGFzayhpbnQgcikgewogICAgICAgICAgICBpbnQgcmVzID0gMDsKICAgICAgICAgICAgZm9yICg7IHIgPj0gMDsgciA9IChyICYgKHIgKyAxKSkgLSAxKQogICAgICAgICAgICAgICAgcmVzICs9IHRyZWVbcl07CiAgICAgICAgICAgIHJldHVybiByZXM7CiAgICAgICAgfQogICAgfTsKfSBfY291bnRfcHJpbWVzX3N0cnVjdF87CgppbnQgbWFpbigpIHsKICAgIGlvc19iYXNlOjpzeW5jX3dpdGhfc3RkaW8oZmFsc2UpOyBjaW4udGllKE5VTEwpOyBjb3V0LnRpZShOVUxMKTsKCiAgICB2ZWN0b3I8bGw+IG5zID0geyhsbCkxZTEwLCAobGwpMWUxMSwgKGxsKTFlMTIsIChsbCkxZTEzfTsKICAgIGZvciAobGwgbiA6IG5zKSB7CiAgICAgICAgYXV0byBzdGFydF90aW1lID0gY2xvY2soKTsKICAgICAgICBjb3V0IDw8ICJuID0gIiA8PCAoZG91YmxlKW4gPDwgZW5kbDsKICAgICAgICBsbCByZXMgPSBfY291bnRfcHJpbWVzX3N0cnVjdF90XygpLmNvdW50X3ByaW1lcyhuKTsKICAgICAgICBjb3V0IDw8ICJyZXN1bHQ6ICIgPDwgcmVzIDw8IGVuZGw7CiAgICAgICAgY291dCA8PCAidGltZTogIiA8PCAoZG91YmxlKShjbG9jaygpIC0gc3RhcnRfdGltZSkgLyBDTE9DS1NfUEVSX1NFQyA8PCAicyIgPDwgZW5kbDsKICAgICAgICBjb3V0IDw8IGVuZGw7CiAgICB9CgogICAgcmV0dXJuIDA7Cn0K