-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNumber_Theory.cpp
More file actions
149 lines (123 loc) · 5.5 KB
/
Number_Theory.cpp
File metadata and controls
149 lines (123 loc) · 5.5 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <bitset> // compact STL for Sieve, more efficient than vector<bool>!
#include <cmath>
#include <cstdio>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef map<int, int> mii;
ll _sieve_size;
bitset<10000010> bs; // 10^7 should be enough for most cases
vi primes; // compact list of primes in form of vector<int>
// first part
void sieve(ll upperbound) { // create list of primes in [0..upperbound]
_sieve_size = upperbound + 1; // add 1 to include upperbound
bs.set(); // set all bits to 1
bs[0] = bs[1] = 0; // except index 0 and 1
for (ll i = 2; i <= _sieve_size; i++) if (bs[i]) {
// cross out multiples of i starting from i * i!
for (ll j = i * i; j <= _sieve_size; j += i) bs[j] = 0;
primes.push_back((int)i); // also add this vector containing list of primes
} } // call this method in main method
bool isPrime(ll N) { // a good enough deterministic prime tester
if (N <= _sieve_size) return bs[N]; // O(1) for small primes
for (int i = 0; i < (int)primes.size(); i++)
if (N % primes[i] == 0) return false;
return true; // it takes longer time if N is a large prime!
} // note: only work for N <= (last prime in vi "primes")^2
// second part
vi primeFactors(ll N) { // remember: vi is vector of integers, ll is long long
vi factors; // vi `primes' (generated by sieve) is optional
ll PF_idx = 0, PF = primes[PF_idx]; // using PF = 2, 3, 4, ..., is also ok
while (N != 1 && (PF * PF <= N)) { // stop at sqrt(N), but N can get smaller
while (N % PF == 0) { N /= PF; factors.push_back(PF); } // remove this PF
PF = primes[++PF_idx]; // only consider primes!
}
if (N != 1) factors.push_back(N); // special case if N is actually a prime
return factors; // if pf exceeds 32-bit integer, you have to change vi
}
// third part
ll numPF(ll N) {
ll PF_idx = 0, PF = primes[PF_idx], ans = 0;
while (N != 1 && (PF * PF <= N)) {
while (N % PF == 0) { N /= PF; ans++; }
PF = primes[++PF_idx];
}
if (N != 1) ans++;
return ans;
}
ll numDiffPF(ll N) {
ll PF_idx = 0, PF = primes[PF_idx], ans = 0;
while (N != 1 && (PF * PF <= N)) {
if (N % PF == 0) ans++; // count this pf only once
while (N % PF == 0) N /= PF;
PF = primes[++PF_idx];
}
if (N != 1) ans++;
return ans;
}
ll sumPF(ll N) {
ll PF_idx = 0, PF = primes[PF_idx], ans = 0;
while (N != 1 && (PF * PF <= N)) {
while (N % PF == 0) { N /= PF; ans += PF; }
PF = primes[++PF_idx];
}
if (N != 1) ans += N;
return ans;
}
ll numDiv(ll N) {
ll PF_idx = 0, PF = primes[PF_idx], ans = 1; // start from ans = 1
while (N != 1 && (PF * PF <= N)) {
ll power = 0; // count the power
while (N % PF == 0) { N /= PF; power++; }
ans *= (power + 1); // according to the formula
PF = primes[++PF_idx];
}
if (N != 1) ans *= 2; // (last factor has pow = 1, we add 1 to it)
return ans;
}
ll sumDiv(ll N) {
ll PF_idx = 0, PF = primes[PF_idx], ans = 1; // start from ans = 1
while (N != 1 && (PF * PF <= N)) {
ll power = 0;
while (N % PF == 0) { N /= PF; power++; }
ans *= ((ll)pow((double)PF, power + 1.0) - 1) / (PF - 1); // formula
PF = primes[++PF_idx];
}
if (N != 1) ans *= ((ll)pow((double)N, 2.0) - 1) / (N - 1); // last one
return ans;
}
ll EulerPhi(ll N) {
ll PF_idx = 0, PF = primes[PF_idx], ans = N; // start from ans = N
while (N != 1 && (PF * PF <= N)) {
if (N % PF == 0) ans -= ans / PF; // only count unique factor
while (N % PF == 0) N /= PF;
PF = primes[++PF_idx];
}
if (N != 1) ans -= ans / N; // last factor
return ans;
}
int main() {
// first part: the Sieve of Eratosthenes
sieve(10000000); // can go up to 10^7 (need few seconds)
printf("%d\n", isPrime(2147483647)); // 10-digits prime
printf("%d\n", isPrime(136117223861LL)); // not a prime, 104729*1299709
// second part: prime factors
vi res = primeFactors(2147483647); // slowest, 2147483647 is a prime
for (vi::iterator i = res.begin(); i != res.end(); i++) printf("> %d\n", *i);
res = primeFactors(136117223861LL); // slow, 2 large pfactors 104729*1299709
for (vi::iterator i = res.begin(); i != res.end(); i++) printf("# %d\n", *i);
res = primeFactors(142391208960LL); // faster, 2^10*3^4*5*7^4*11*13
for (vi::iterator i = res.begin(); i != res.end(); i++) printf("! %d\n", *i);
//res = primeFactors((ll)(1010189899 * 1010189899)); // "error"
//for (vi::iterator i = res.begin(); i != res.end(); i++) printf("^ %d\n", *i);
// third part: prime factors variants
printf("numPF(%d) = %lld\n", 50, numPF(50)); // 2^1 * 5^2 => 3
printf("numDiffPF(%d) = %lld\n", 50, numDiffPF(50)); // 2^1 * 5^2 => 2
printf("sumPF(%d) = %lld\n", 50, sumPF(50)); // 2^1 * 5^2 => 2 + 5 + 5 = 12
printf("numDiv(%d) = %lld\n", 50, numDiv(50)); // 1, 2, 5, 10, 25, 50, 6 divisors
printf("sumDiv(%d) = %lld\n", 50, sumDiv(50)); // 1 + 2 + 5 + 10 + 25 + 50 = 93
printf("EulerPhi(%d) = %lld\n", 50, EulerPhi(50)); // 20 integers < 50 are relatively prime with 50
return 0;
}