-
Notifications
You must be signed in to change notification settings - Fork 2
/
NumberTheory.java
executable file
·173 lines (162 loc) · 5.25 KB
/
NumberTheory.java
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import java.util.*;
class NumberTheory {
static ArrayList<Integer> primes = new ArrayList();
/**Generate all prime numbers less than or equal to n. Sieve of Eratosthenes
* There are approximately n/log n prime numbers < n
* O(n*log(log n))
* @param n The largest number to consider
* @return All prime numbers less than or equal to n*/
static ArrayList<Integer> primes(int n) {
boolean[] visited = new boolean[n+1];
for(int p = 2; p <= n; ++p)
if(!visited[p]) {
primes.add(p);
for(int m = p*p; m <= n && m > p; m += p)
visited[m] = true;
}
return primes;
}
/**Generate a table specifying whether a number is prime or not, for all numbers up to n. Sieve of Eratosthenes
* There are approximately n/log n prime numbers < n
* O(n*log(log n))
* @param n The largest number to consider
* @return Which numbers less than or equal to n are prime*/
static boolean[] primeTable(int n) {
boolean[] primes = new boolean[n+1];
Arrays.fill(primes, true);
primes[0] = false;
primes[1] = false;
for(int p = 2; p <= Math.sqrt(n); ++p)
if(primes[p]) {
for(int m = p*p; m <= n; m += p)
primes[m] = false;
}
return primes;
}
/**Factorize the integer n. primes() must have been run beforehand
* O(sqrt n)
* @param n The number to factorize
* @return A list of primes and their power in the factorization*/
static ArrayList<Pair> factorize(int n) {
ArrayList<Pair> factors = new ArrayList();
for(int p : primes) {
if(p*p > n)
break;
int count = 0;
while(n%p == 0) {
count++;
n /= p;
}
if(count > 0)
factors.add(new Pair(p, count));
}
if(n > 1)
factors.add(new Pair(n, 1));
return factors;
}
/**Count how many times n! can be divided by the prime number p
* <=> Count how many times p appears in the factorization of n!
* O(log n)
* @param n The base of the factorial
* @param p The factor to count
* @return How many times n! can be divided by the prime number p*/
static int factorialDivisible(int n, int p) {
int factor = p;
int count = 0;
while(true) {
int times = n/factor;
if(times <= 0)
break;
count += times;
factor *= p;
}
return count;
}
/**Generate all binomial coefficients a choose b where a, b <= n
* O(n^2)
* @param n The largest binomial coefficient to generate
* @return An array where index [i][j] is the binomial coefficient i choose j*/
static int[][] binomialCoefficients(int n) {
int[][] pascal = new int[n+1][n+1];
for(int i = 1; i <= n; ++i) {
pascal[i][0] = 1;
for(int j = 1; j <= i; ++j)
pascal[i][j] = pascal[i-1][j-1] + pascal[i-1][j];
}
return pascal;
}
/**Find the binomial coefficient n choose k = n!/(k!*(n-k)!)
* O(k) time, O(1) space
* @param n Number of elements to choose from
* @param k Number of elements to choose
* @return Number of ways to choose k from n elements*/
static long binomialCoefficient(int n, int k) {
long res = 1;
if(n/2 < k)
k = n-k;
for(int i = 1; i <= k; ++i) {
res *= (n-i+1);
res /= i;
}
return res;
}
/**Generate the n first Catalan numbers
* O(n^2)
* @param n How many numbers to generate
* @return An array where index [i] is the i-th Catalan number*/
static int[] catalanNumbers(int n) {
int[] catalan = new int[n+1];
catalan[0] = 1;
for(int i = 1; i <= n; ++i)
for(int j = 0; j < i; ++j)
catalan[i] += catalan[j]*catalan[i-j-1];
return catalan;
}
/**Find the greatest common divisor of a and b. Euclid's division algorithm
* O(log min(|a|, |b|))
* @param a The first number
* @param b The second number
* @return The greatest common divisor*/
static int gcd(int a, int b) {
while(b != 0) {
int t = b;
b = a%b;
a = t;
}
return Math.abs(a);
}
/**Calculate Bezout's identity: x and y, such that a*x+b*y = gcd(a, b). Euclid's extended algorithm
* O((log min(|a|, |b|))^2)
* @param a The first number
* @param b The second number
* @return <x, y, z> such that a*x+b*y = gcd(a, b) = z*/
static Triple bezoutsIdentity(int a, int b) {
int[] t = {1, 0};
int[] s = {0, 1};
int[] r = {b, a};
int pos = 0;
while(r[pos] != 0) {
int npos = (pos+1)%2;
int q = r[npos]/r[pos];
r[npos] -= q*r[pos];
s[npos] -= q*s[pos];
t[npos] -= q*t[pos];
pos = npos;
}
pos = (pos+1)%2;
if(r[pos] < 0)
return new Triple(-s[pos], -t[pos], -r[pos]);
return new Triple(s[pos], t[pos], r[pos]);
}
/**Calculate the modular multiplicative inverse of a modulo m. Euclid's extended algorithm
* O((log min(|a|, |b|))^2)
* @param a A non-negative integer
* @param m An integer > 1
* @return The modular multiplicative inverse x such that ax === 1 (mod m), -1 if a and m are not coprime*/
static int multiplicativeInverse(int a, int m) {
Triple t = bezoutsIdentity(a, m);
if(t.trd != 1)
return -1;
return (t.fst+m)%m;
}
}