Skip to main content

Combinations and Modular Inverse

1. Combinations

  • Purpose: Calculates the number of ways to choose r items from n items, where order doesn't matter
  • Example: If you have 5 colors and want to pick 2, nCr(5,2) tells you how many different color pairs are possible
  • Formula: C(n,r) = n!/(r! * (n-r)!)

2. Modular Inverse:

  • Purpose: Used when we need to perform division in modular arithmetic
  • When we calculate large combinations, we often need to take modulo to prevent overflow
  • Division in modular arithmetic isn't straightforward, so we use modular multiplicative inverse
  • For (a/b) % m, we calculate (a * modInverse(b,m)) % m
// Calculate combinations C(n,r) using modular arithmetic
function modInverse(a, m) {
// Extended Euclidean Algorithm to find modular multiplicative inverse
let m0 = m;
let x0 = 0;
let x1 = 1;

if (m === 1) return 0;

while (a > 1) {
const q = Math.floor(a / m);
let t = m;

m = a % m;
a = t;
t = x0;

x0 = x1 - q * x0;
x1 = t;
}

return x1 < 0 ? x1 + m0 : x1;
}

function nCr(n, r, mod = 1e9 + 7) {
if (r > n) return 0;
if (r === 0 || r === n) return 1;

// Calculate using formula: C(n,r) = n!/(r! * (n-r)!)
let numerator = 1;
let denominator = 1;

for (let i = 0; i < r; i++) {
numerator = (numerator * (n - i)) % mod;
denominator = (denominator * (i + 1)) % mod;
}

// Use modular inverse for division
return (numerator * modInverse(denominator, mod)) % mod;
}

// Example usage
console.log(nCr(5, 2)); // Calculates 5C2 = 10
console.log(nCr(10, 3)); // Calculates 10C3 = 120

For Big Numbers

const kMod = BigInt(1e9 + 7); // Modulo 10^9+7

// Modular exponentiation
const modPow = (base, exp, mod) => {
let result = BigInt(1);
while (exp > 0) {
if (exp % BigInt(2) === BigInt(1)) result = (result * base) % mod;
base = (base * base) % mod;
exp >>= BigInt(1); // Bitwise shift for efficiency
}
return result;
};

// Compute (nCr) % mod using modular inverse
const comb = (n, r, mod = kMod) => {
if (r > n) return BigInt(0);

let numerator = BigInt(1), denominator = BigInt(1);
for (let i = BigInt(0); i < r; i++) {
numerator = (numerator * (n - i)) % mod;
denominator = (denominator * (i + BigInt(1))) % mod;
}

// Compute modular inverse of denominator using Fermat’s theorem
return (numerator * modPow(denominator, mod - BigInt(2), mod)) % mod;
};

// Example usage
console.log(comb(BigInt(5), BigInt(2))); // 10
console.log(comb(BigInt(10), BigInt(3))); // 120
console.log(comb(BigInt(1000), BigInt(500))); // Large nCr % 10^9+7
/*
10n
120n
159835829n
*/