Using prime factorization, any number can be represented as:
where are distinct prime factors and are their respective powers.
Number of Divisors
Formula:
Mathematical Proof
By the Fundamental Theorem of Arithmetic, any integer can be uniquely factorized as:
Any divisor of must also be composed of the same prime factors, but raised to some power less than or equal to the powers in . Therefore, takes the form:
where each exponent must satisfy the condition .
For every prime factor , you can choose its exponent in exactly different ways (since you can choose ).
Time Complexity:
Space Complexity:
long long countDivisors(long long n) {
long long count = 1;
for (long long d = 2; d * d <= n; d++) {
if (n % d == 0) {
int e = 0;
while (n % d == 0) {
e++;
n /= d;
}
count *= (e + 1);
}
}
if (n > 1) {
count *= (1 + 1);
}
return count;
}Algorithm:
- Handle edge cases early by returning
0if . - Initialize a running total
count = 1. - Iterate through potential prime factors from up to (using instead of prevents integer overflow for very large numbers).
- If divides , determine its frequency (exponent ) by repeatedly dividing by .
- Multiply the running
countby . - If after the loop completes, the remaining value is a prime factor itself (with an exponent of ); multiply the final
countby (which is ).
Sum of Divisors
Formula:
Mathematical Proof
Consider the algebraic expansion of the following product of polynomials:
When you expand this product, every resulting term is formed by choosing exactly one power from each bracket. This means every term takes the exact form of a unique divisor .
Because every possible divisor is generated exactly once, the evaluated sum of this expanded polynomial is exactly the sum of all divisors of .
Notice that each bracket is a finite geometric series. The previously known formula for the sum of a finite geometric series is:
Substituting this known sum formula into each bracket of our product yields the final formula:
Time Complexity:
Space Complexity:
long long divisorFunctions(long long n, bool wantSum) {
long long count = 1;
long long sum = 1;
for (long long d = 2; d * d <= n; d++) {
if (n % d == 0) {
int e = 0;
long long p_pow = d;
while (n % d == 0) {
e++;
p_pow *= d;
n /= d;
}
count *= (e + 1);
sum *= (p_pow - 1) / (d - 1);
}
}
if (n > 1) {
count *= (1 + 1);
sum *= (n * n - 1) / (n - 1); // equivalent to (n + 1)
}
return wantSum ? sum : count;
}
Algorithm:
- Find the prime factorization of using Trial Division.
- For each prime factor , count its frequency (exponent ).
- Maintain running totals for
countandsumby multiplying the respective formula terms at each prime step.
Euler’s Totient Function
Counts the number of positive integers up to that are relatively prime (coprime) to .
Formula:
*(Where iterates over all distinct prime factors of )
Mathematical Proof
This formula is derived using the Principle of Inclusion-Exclusion (PIE).
Let the distinct prime factors of be . We want to find the count of integers in the set that are coprime to (meaning they are not divisible by any of ‘s prime factors).
- The total number of integers in the range is .
- The number of integers divisible by a prime is . We must subtract these.
- However, numbers divisible by both and were subtracted twice. We must add them back. There are such numbers.
- Numbers divisible by three primes were added back too many times, so we subtract them again: , and so on.
By PIE, the number of integers coprime to is:
If we factor out the common term , we get:
This alternating sum of fractions is the exact algebraic expansion of the product:
Time Complexity:
Space Complexity:
int phi(int n) {
int result = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
while (n % i == 0) n /= i;
result -= result / i; // equivalent to result = result * (1 - 1/i)
}
}
if (n > 1) {
result -= result / n;
}
return result;
}
Algorithm:
- Initialize
result = n. - Iterate through possible prime factors from to .
- If divides , it is a prime factor. Remove all occurrences of from to avoid counting the same factor twice.
- Multiply the
resultby (handled programmatically asresult -= result / i). - If after the loop, the remaining is a prime factor itself; apply the formula one last time for .
GCD & LCM
The Euclidean algorithm is the standard way to find the largest number that divides two numbers.
Formula for LCM:
Mathematical Proof
Let represent all the distinct prime factors present in either or . We can express and using prime factorization as:
(If a prime factor is present in one number but not the other, its exponent is ).
Based on the prime factorization method:
- The GCD takes the lowest power of each prime:
- The LCM takes the highest power of each prime:
Now, multiply the GCD and the LCM together:
For any two real numbers and , the sum of their minimum and maximum is simply the sum of the numbers themselves: .
Applying this logic to our exponents:
We can split this product back into two parts:
Therefore, . Rearranging this equation isolates the LCM:
Time Complexity:
Space Complexity: (due to recursion stack)
long long gcd(long long a, long long b) {
if (b == 0) return a;
return gcd(b, a % b);
}
long long lcm(long long a, long long b) {
return (a / gcd(a, b)) * b;
}Algorithm:
- Base case: If is , the GCD is .
- Otherwise, recursively call the function replacing with , and with the remainder of divided by ().
Primality Test
Standard trial division test to check if a single number is prime.
- Time Complexity:
- Space Complexity:
bool isPrime(int n) {
if(n <= 1) return false;
if(n <= 3) return true;
if(n % 2 == 0 || n % 3 == 0) return false;
for(int i = 5; i * i <= n; i += 6) {
if(n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}Algorithm
- Handle small cases (≤ 3) directly.
- Check divisibility by 2 and 3.
- Then test all possible divisors from 5 up to √n, stepping by 6 (covers numbers of the form 6k±1).
- If any divisor divides
n, it’s composite; otherwise it’s prime.
Linear Sieve
Computes the Smallest Prime Factor (SPF) and finds primes strictly in linear time.
- Time Complexity:
- Space Complexity:
vector<int> linearSieve(int n) {
vector<int> lp(n + 1, 0), primes;
for(int i = 2; i <= n; i++) {
if(lp[i] == 0) { lp[i] = i; primes.push_back(i); }
for(int p : primes) {
if(p > lp[i] || 1LL * i * p > n) break;
lp[i * p] = p;
}
}
return primes;
}Algorithm
- Maintain an array
lpthat stores the smallest prime factor for each number. - Iterate
ifrom 2 ton. Iflp[i]is 0,iis prime – store its SPF and add it to the prime list. - For each prime
palready found, assignpas the SPF ofi*p, stopping whenpexceedslp[i]ori*pexceedsn. - This ensures every composite is generated exactly once.
Sieve of Eratosthenes
Generates all prime numbers up to a given limit .
- Time Complexity:
- Space Complexity:
vector<int> sieve(int n) {
vector<bool> isPrime(n + 1, true);
vector<int> primes;
isPrime[0] = isPrime[1] = false;
for(int i = 2; i <= n; i++) {
if(isPrime[i]) {
primes.push_back(i);
for(long long j = 1LL * i * i; j <= n; j += i)
isPrime[j] = false;
}
}
return primes;
}Algorithm
- Start with all numbers from 2 to
nmarked as prime. - For each
ithat is still marked prime, add it to the list and mark all its multiples (starting fromi*i) as non‑prime. - Return the list of primes.
Segmented Sieve
Finds all prime numbers in a specific range . Highly useful when is large but the difference is small enough to fit in memory.
- Time Complexity:
- Space Complexity:
vector<int> segmentedSieve(long long L, long long R) {
long long lim = sqrt(R);
vector<int> base = sieve(lim);
vector<bool> isPrime(R - L + 1, true);
for(long long p : base) {
long long start = max(p * p, (L + p - 1) / p * p);
for(long long j = start; j <= R; j += p)
isPrime[j - L] = false;
}
vector<int> primes;
for(long long i = 0; i <= R - L; i++)
if(isPrime[i] && L + i >= 2) primes.push_back(L + i);
return primes;
}Algorithm
- Generate all primes up to √R (these will be used to cross out composites).
- Create a boolean array for the range
[L, R]and initialise all as prime. - For each base prime
p, find its first multiple within[L, R]and mark every multiple ofpin that range as non‑prime. - Scan the range and collect the numbers still marked prime.
Prime Factorization using SPF
Uses precomputed Smallest Prime Factors (SPF) to answer prime factorization queries almost instantly.
- Build Time:
- Query Time: per factorization
- Space Complexity:
vector<int> spf;
void buildSPF(int n) {
spf.resize(n + 1);
for(int i = 0; i <= n; i++) spf[i] = i;
for(int i = 2; i * i <= n; i++) {
if(spf[i] == i) {
for(int j = i * i; j <= n; j += i)
if(spf[j] == j) spf[j] = i;
}
}
}
vector<pair<int,int>> factorize(int x) {
vector<pair<int,int>> res;
while(x > 1) {
int p = spf[x], cnt = 0;
while(x % p == 0) { x /= p; cnt++; }
res.push_back({p, cnt});
}
return res;
}Algorithm
- Build: Initialize
spf[i] = i. For each primei, iterate over its multiples starting fromi*iand setspf[j] = iif it hasn’t been set yet. - Factorize: Repeatedly extract the smallest prime factor
spf[x], count how many times it dividesx, divide it out, and record the pair(prime, exponent).