Primes and factors
A number $n>1$ is a prime if its only positive factors are 1 and $n$. For example, 7, 19 and 41 are primes, but 35 is not a prime, because $5 \cdot 7 = 35$. For every number $n>1$, there is a unique prime factorization \[ n = p_1^{\alpha_1} p_2^{\alpha_2} \cdots p_k^{\alpha_k},\] where $p_1,p_2,\ldots,p_k$ are distinct primes and $\alpha_1,\alpha_2,\ldots,\alpha_k$ are positive numbers. For example, the prime factorization for 84 is \[ 84 = 2^2 \cdot 3^1 \cdot 7^1 \]
The number of factors of a number $n$ is
\[ \tau(n)=\prod_{i=1}^k (\alpha_i+1) \]
because for each prime $p_i$, there are $\alpha_i+1$ ways to choose how many times it appears in the factor. For example, the number of factors of 84 is $\tau(84)=3 \cdot 2 \cdot 2 = 12$. The factors are
$$1, 2, 3, 4, 6, 7, 12, 14, 21, 28, 42, 84$$
The sum of factors of $n$ is \[ \sigma(n)=\prod_{i=1}^k (1+p_i+\ldots+p_i^{\alpha_i}) = \prod_{i=1}^k \frac{p_i^{a_i+1}-1}{p_i-1} \] where the latter formula is based on the geometric progression formula. For example, the sum of factors of 84 is \[ \sigma(84)=\frac{2^3-1}{2-1} \cdot \frac{3^2-1}{3-1} \cdot \frac{7^2-1}{7-1} = 7 \cdot 4 \cdot 8 = 224 \]
The product of factors of $n$ is \[ \mu(n)=n^{\tau(n)/2} \] because we can form $\tau(n)/2$ pairs from the factors, each with product $n$. For example, the factors of 84 produce the pairs $1 \cdot 84$, $2 \cdot 42$, $3 \cdot 28$, etc., and the product of the factors is $\mu(84)=84^6=351298031616$.
A number $n$ is called a perfect number if $n=\sigma(n)-n$, i.e., $n$ equals the sum of its factors between $1$ and $n-1$. For example, 28 is a perfect number, because $28=1+2+4+7+14$.
Number of primes
It is easy to show that there is an infinite number of primes. If the number of primes would be finite, we could construct a set $P={p_1,p_2,\ldots,p_n}$ that would contain all the primes. For example, $p_1=2$, $p_2=3$, $p_3=5$, and so on. However, using $P$, we could form a new prime \[p_1 p_2 \cdots p_n+1\] that is larger than all elements in $P$. This is a contradiction, and the number of primes has to be infinite.
Density of primes
The density of primes means how often there are primes among the numbers. Let $\pi(n)$ denote the number of primes between $1$ and $n$. For example, $\pi(10)=4$, because there are 4 primes between $1$ and $10$: 2, 3, 5 and 7.
It is possible to show that
\[ \pi(n) \approx \frac{n}{\ln n} \]
which means that primes are quite frequent. For example, the number of primes between $1$ and $10^6$ is $\pi(10^6)=78498$, and $10^6 / \ln 10^6 \approx 72382$.
Conjectures
There are many conjectures involving primes. Most people think that the conjectures are true, but nobody has been able to prove them. For example, the following conjectures are famous:
- Goldbach's conjecture: Each even integer $n>2$ can be represented as a sum $n=a+b$ so that both $a$ and $b$ are primes.
- Twin prime conjecture: There is an infinite number of pairs of the form ${p,p+2}$, where both $p$ and $p+2$ are primes.
- Legendre's conjecture: There is always a prime between numbers $n^2$ and $(n+1)^2$, where $n$ is any positive integer.
Basic algorithms
If a number $n$ is not prime, it can be represented as a product $a \cdot b$, where $a \le \sqrt n$ or $b \le \sqrt n$, so it certainly has a factor between $2$ and $\lfloor \sqrt n \rfloor$. Using this observation, we can both test if a number is prime and find the prime factorization of a number in $O(\sqrt n)$ time.
The following function prime
checks
if the given number $n$ is prime.
The function attempts to divide $n$ by
all numbers between $2$ and $\lfloor \sqrt n \rfloor$,
#![allow(unused)] fn main() { fn prime(n: usize) -> bool { if n < 2 { return false } let mut x = 2; while x*x <= n{ if n%x == 0 { return false } x+=1 } true } }
The following function factors
constructs a vector that contains the prime
factorization of $n$.
The function divides $n$ by its prime factors,
and adds them to the vector.
The process ends when the remaining number $n$
has no factors between $2$ and $\lfloor \sqrt n \rfloor$.
If $n>1$, it is prime and the last factor.
#![allow(unused)] fn main() { println!("n = 100 -> {:?}", factors(100)); fn factors(mut n: isize) -> Vec<isize>{ let mut f = Vec::new(); let mut x = 2; while x*x <= n { while n%x == 0 { f.push(x); n/=x; } x+=1; } if n > 1 { f.push(n) } f } }
Note that each prime factor appears in the vector as many times as it divides the number. For example, $24=2^3 \cdot 3$, so the result of the function is [2,2,2,3].
Sieve of Eratosthenes
The sieve of Eratosthenes is a preprocessing algorithm that builds an array using which we can efficiently check if a given number between $2 \ldots n$ is prime and, if it is not, find one prime factor of the number.
The algorithm builds an array sieve
whose positions $2,3,\ldots,n$ are used.
The value sieve[k]=0
means
that $k$ is prime,
and the value sieve[k] != 0
means that $k$ is not a prime and one
of its prime factors is sieve[k]
.
The algorithm iterates through the numbers $2 \ldots n$ one by one. Always when a new prime $x$ is found, the algorithm records that the multiples of $x$ ($2x,3x,4x,\ldots$) are not primes, because the number $x$ divides them.
For example, if $n=20$, the array is as follows:
The following code implements the sieve of
Eratosthenes.
The code assumes that each element of
sieve
is initially zero.
#![allow(unused)] fn main() { let mut n = 20; let mut sieve = vec![0_usize;n+1]; for x in 2..=n { if sieve[x] == 0 { let mut u = 2*x; while u <= n { sieve[u] = x; u+=x; } } } println!("{:?}", &sieve[2..]); }
The inner loop of the algorithm is executed $n/x$ times for each value of $x$. Thus, an upper bound for the running time of the algorithm is the harmonic sum \[ \sum_{x=2}^n n/x = n/2 + n/3 + n/4 + \cdots + n/n = O(n \log n) \]
In fact, the algorithm is more efficient, because the inner loop will be executed only if the number $x$ is prime. It can be shown that the running time of the algorithm is only $O(n \log \log n)$, a complexity very near to $O(n)$.
Euclid's Algorithm
The greatest common divisor of numbers $a$ and $b$, $\gcd(a,b)$, is the greatest number that divides both $a$ and $b$, and the least common multiple of $a$ and $b$, $\textrm{lcm}(a,b)$, is the smallest number that is divisible by both $a$ and $b$. For example, $\gcd(24,36)=12$ and $\textrm{lcm}(24,36)=72$.
The greatest common divisor and the least common multiple are connected as follows: \[ \textrm{lcm}(a,b)=\frac{ab}{\textrm{gcd}(a,b)} \]
Euclid's algorithm1 provides an efficient way to find the greatest common divisor of two numbers. The algorithm is based on the following formula:
\[ \textrm{gcd}(a,b) = \begin{cases} a & b = 0\\ \textrm{gcd}(b,a \bmod b) & b \neq 0\ \end{cases} \]
For example, \[ \textrm{gcd}(24,36) = \textrm{gcd}(36,24) = \textrm{gcd}(24,12) = \textrm{gcd}(12,0)=12 \]
The algorithm can be implemented as follows:
#![allow(unused)] fn main() { fn gcd(a: usize, b:usize)-> usize{ if b == 0 {return a} gcd(b, a%b) } println!("gcd between 100 and 85 is {:?}", gcd(100, 85)); }
It can be shown that Euclid's algorithm works in $O(\log n)$ time, where $n=\min(a,b)$. The worst case for the algorithm is the case when $a$ and $b$ are consecutive Fibonacci numbers. For example, \[ \textrm{gcd}(13,8)=\textrm{gcd}(8,5) =\textrm{gcd}(5,3)=\textrm{gcd}(3,2)=\textrm{gcd}(2,1)=\textrm{gcd}(1,0)=1 \]
Euler's totient function
Numbers $a$ and $b$ are \key{coprime} if $\textrm{gcd}(a,b)=1$. Euler's totient function $\varphi(n)$ %\footnote{Euler presented this function in 1763.} gives the number of coprime numbers to $n$ between $1$ and $n$. For example, $\varphi(12)=4$, because 1, 5, 7 and 11 are coprime to 12.
The value of $\varphi(n)$ can be calculated from the prime factorization of $n$ using the formula
\[ \varphi(n) = \prod_{i=1}^k p_i^{\alpha_i-1}(p_i-1) \]
For example, $\varphi(12)=2^1 \cdot (2-1) \cdot 3^0 \cdot (3-1)=4$. Note that $\varphi(n)=n-1$ if $n$ is prime.
1 Euclid was a Greek mathematician who lived in about 300 BC. This is perhaps the first known algorithm in history.