-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprimepi.cpp
More file actions
123 lines (111 loc) · 2.8 KB
/
Copy pathprimepi.cpp
File metadata and controls
123 lines (111 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <bits/stdc++.h>
#define f first
#define s second
#define endl '\n'
#define pb push_back
#define pii pair<int, int>
#define vi vector<int>
#define vvi vector<vi>
#define pii pair<int, int>
#define vpii vector<pii>
#define vvpii vector<vpii>
typedef long long ll;
typedef long double ld;
using namespace std;
template<class T> using minheap = priority_queue<T, vector<T>, greater<T>>;
template<typename T> void setmax(T& a, T b) { a = max(a, b); };
template<typename T> void setmin(T& a, T b) { a = min(a, b); };
template<typename T> bool in(T lo, T v, T hi) { return lo <= v && v <= hi; };
struct timestamp {
string algo;
ld A, B;
timestamp(string _algo) {
algo = _algo;
A = B = clock();
}
void print() {
ld B_ = clock();
ld section = (B_ - B) / CLOCKS_PER_SEC;
ld cumulative = (B_ - A) / CLOCKS_PER_SEC;
cout << algo << " profile(seconds): section " << section << " cumulative: " << cumulative << endl << flush;
B = B_;
}
} t("pe 501");
/*
Meissel-Lehmer algorithm
*/
const int MX = 4e7; // MX is the maximum value of sqrt(N) + 2
bool isPrime[MX];
int primePi[MX];
vector<ll> P;
void init() {
for (int i = 2; i < MX; i++)
isPrime[i] = true;
for (int i = 2; i < MX; i++) {
if (isPrime[i]) {
for (int j = i + i; j < MX; j += i) {
isPrime[j] = false;
}
}
}
for (int i = 2; i < MX; i++) {
primePi[i] = primePi[i - 1] + isPrime[i];
}
for (int i = 2; i < MX; i++) {
if (isPrime[i]) {
P.push_back(i);
}
}
}
/*
number of integers in 2..N whose smallest prime factor is <= P[K]
*/
ll rec(ll N, int K) {
if (N <= 1 || K < 0) return 0;
if (N <= P[K]) return N - 1;
if (N < MX && ll(P[K]) * P[K] > N) {
return (N - 1) - (primePi[N] - primePi[P[K]]);
}
const int LIM = 250;
static int memo[LIM * LIM][LIM];
bool do_mem = N < LIM * LIM;
if (do_mem && memo[N][K]) return memo[N][K];
ll result = N / P[K] - rec(N / P[K], K - 1) + rec(N, K - 1);
if (do_mem) memo[N][K] = result;
return result;
}
ll count_primes(ll N) {
if (N < MX)
return primePi[N];
static map<ll, ll> memo;
if (memo.count(N)) return memo[N];
int K = primePi[(int)sqrt(N) + 1];
return memo[N] = (N - 1) - (rec(N, K) - primePi[P[K]]);
}
ll power(ll a, ll b) {
if (b == 0) return 1;
return power(a, b - 1) * a;
}
int main(){
init();
ll n = 1e12;
ll result = 0;
for (int i = 0; power(P[i], 7) <= n; i++) {
result++;
}
for (int i = 0; power(P[i], 3) <= n; i++) {
ll qmax = n / power(P[i], 3);
result += count_primes(qmax);
if (qmax >= P[i])
result--;
}
for (int i = 0; power(P[i], 3) <= n; i++) {
for (int j = i + 1; j < P.size() && P[i] * P[j] * P[j] < n; j++) {
ll qmax = n / (P[i] * P[j]);
result += count_primes(qmax) - j - 1;
}
}
cout << result << endl;
t.print();
return 0;
}