Docs
/
DSA Advanced
Chapter 19
19 — Math & Number Theory
GCD & LCM
function gcd(a: number, b: number): number {
while (b) { [a, b] = [b, a % b]; }
return a;
}
function lcm(a: number, b: number): number {
return (a / gcd(a, b)) * b; // Divide first to avoid overflow
}
// Extended GCD: find x, y such that ax + by = gcd(a,b)
function extGcd(a: number, b: number): [number, number, number] {
if (b === 0) return [a, 1, 0];
const [g, x1, y1] = extGcd(b, a % b);
return [g, y1, x1 - Math.floor(a / b) * y1];
}
Prime Numbers
Sieve of Eratosthenes
function sieve(n: number): boolean[] {
const isPrime = new Array(n + 1).fill(true);
isPrime[0] = isPrime[1] = false;
for (let i = 2; i * i <= n; i++) {
if (isPrime[i]) {
for (let j = i * i; j <= n; j += i) {
isPrime[j] = false;
}
}
}
return isPrime;
}
// Time: O(n log log n), Space: O(n)
Primality Test
function isPrime(n: number): boolean {
if (n < 2) return false;
if (n < 4) return true;
if (n % 2 === 0 || n % 3 === 0) return false;
for (let i = 5; i * i <= n; i += 6) {
if (n % i === 0 || n % (i + 2) === 0) return false;
}
return true;
}
// Time: O(√n)
Prime Factorization
function primeFactors(n: number): Map<number, number> {
const factors = new Map<number, number>();
for (let d = 2; d * d <= n; d++) {
while (n % d === 0) {
factors.set(d, (factors.get(d) ?? 0) + 1);
n /= d;
}
}
if (n > 1) factors.set(n, 1);
return factors;
}
Modular Arithmetic
(a + b) % m = ((a % m) + (b % m)) % m
(a * b) % m = ((a % m) * (b % m)) % m
(a - b) % m = ((a % m) - (b % m) + m) % m // +m to avoid negative
(a / b) % m = (a * modInverse(b, m)) % m // Use modular inverse
Modular Inverse
// Fermat's little theorem: a^(-1) ≡ a^(p-2) (mod p), p is prime
function modInverse(a: number, mod: number): number {
return modPow(a, mod - 2, mod);
}
Fast Exponentiation
function modPow(base: number, exp: number, mod: number): number {
let result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = (result * base) % mod;
exp >>= 1;
base = (base * base) % mod;
}
return result;
}
// Time: O(log n)
Combinatorics
// nCr mod p (with precomputed factorials)
const MOD = 1e9 + 7;
function precompute(n: number): { fact: number[]; inv: number[] } {
const fact = new Array(n + 1);
const inv = new Array(n + 1);
fact[0] = 1;
for (let i = 1; i <= n; i++) fact[i] = (fact[i - 1] * i) % MOD;
inv[n] = modPow(fact[n], MOD - 2, MOD);
for (let i = n - 1; i >= 0; i--) inv[i] = (inv[i + 1] * (i + 1)) % MOD;
return { fact, inv };
}
function nCr(n: number, r: number, fact: number[], inv: number[]): number {
if (r < 0 || r > n) return 0;
return (fact[n] * inv[r] % MOD) * inv[n - r] % MOD;
}
Common Interview Problems
Count Primes
function countPrimes(n: number): number {
const isPrime = sieve(n - 1);
return isPrime.filter(Boolean).length;
}
Power of Three
const isPowerOfThree = (n: number) => n > 0 && 1162261467 % n === 0;
// 3^19 = 1162261467 is largest power of 3 in 32-bit int
Happy Number
function isHappy(n: number): boolean {
const seen = new Set<number>();
while (n !== 1 && !seen.has(n)) {
seen.add(n);
n = String(n).split('').reduce((sum, d) => sum + (+d) ** 2, 0);
}
return n === 1;
}
Key Takeaways
- GCD: Euclidean algorithm O(log min(a,b)); LCM = a/gcd × b
- Sieve: O(n log log n) to find all primes up to n
- Modular arithmetic: always mod after each operation to prevent overflow
- Fast exponentiation: O(log n) — essential for large powers with mod
- nCr mod p: precompute factorials + modular inverse