discrete math25 min

Combinatorial Proofs

Bijections and double counting — proving identities by showing two ways to count the same thing

0/9Not Started

Why This Matters

Algebraic proofs of combinatorial identities can be long and mechanical. A combinatorial proof takes a different approach: instead of manipulating symbols, you show that both sides of an identity count the same thing. When you prove C(n,k) = C(n, n-k) by arguing that choosing k items to include is the same as choosing n-k items to exclude, you gain genuine understanding — not just verification.

The two main techniques are bijection (showing a one-to-one correspondence between two sets) and double counting (counting the same set in two different ways to obtain an identity). These proof strategies train the kind of structural thinking that transfers directly to algorithm design. When you recognize a bijection, you can transform one problem into another. When you double count, you find relationships between quantities that seem unrelated.

Define Terms

Visual Model

Combinatorial IdentityC(n,k) = C(n-1,k-1) + C(n-1,k)
Algebraic ProofExpand and simplify
Combinatorial ProofCount the same set two ways
Bijection1-to-1 correspondence
Double CountingTwo ways, same answer
Pascal IdentityInclude or exclude element n
Deep UnderstandingWhy, not just that

The full process at a glance. Click Start tour to walk through each step.

Combinatorial proofs reveal why identities hold by counting the same set in two different ways.

Code Example

Code
// Binomial coefficient: C(n, k) = n! / (k! * (n-k)!)
function choose(n, k) {
  if (k < 0 || k > n) return 0;
  if (k === 0 || k === n) return 1;
  // Use multiplicative formula to avoid large factorials
  let result = 1;
  for (let i = 0; i < Math.min(k, n - k); i++) {
    result = result * (n - i) / (i + 1);
  }
  return Math.round(result);
}

// Verify Pascal Identity: C(n,k) = C(n-1,k-1) + C(n-1,k)
function verifyPascal(n, k) {
  const lhs = choose(n, k);
  const rhs = choose(n - 1, k - 1) + choose(n - 1, k);
  return lhs === rhs;
}

console.log("C(5,2) =", choose(5, 2)); // 10
console.log("C(4,1) + C(4,2) =", choose(4, 1) + choose(4, 2)); // 10
console.log("Pascal identity holds:", verifyPascal(5, 2)); // true

// Verify for many values
let allPass = true;
for (let n = 1; n <= 15; n++) {
  for (let k = 1; k < n; k++) {
    if (!verifyPascal(n, k)) allPass = false;
  }
}
console.log("Pascal identity holds for n=1..15:", allPass); // true

// Symmetry: C(n,k) = C(n, n-k) (bijection proof)
console.log("C(10,3) =", choose(10, 3)); // 120
console.log("C(10,7) =", choose(10, 7)); // 120

// Vandermonde identity: C(m+n,r) = sum of C(m,k)*C(n,r-k)
function verifyVandermonde(m, n, r) {
  const lhs = choose(m + n, r);
  let rhs = 0;
  for (let k = 0; k <= r; k++) {
    rhs += choose(m, k) * choose(n, r - k);
  }
  return lhs === rhs;
}
console.log("Vandermonde C(3+4,3):", verifyVandermonde(3, 4, 3)); // true

// Build Pascal triangle to visualize
function pascalTriangle(rows) {
  const triangle = [];
  for (let n = 0; n < rows; n++) {
    const row = [];
    for (let k = 0; k <= n; k++) {
      row.push(choose(n, k));
    }
    triangle.push(row);
    console.log(row.join(" "));
  }
}
pascalTriangle(6);

Interactive Experiment

Try these exercises:

  • Build the first 10 rows of Pascal triangle. Verify that each entry equals the sum of the two entries above it.
  • Verify the symmetry C(n, k) = C(n, n-k) for all k from 0 to 20 when n = 20.
  • Sum each row of Pascal triangle. What pattern do you see? Can you prove it combinatorially? (Hint: each subset either includes or excludes each element.)
  • Verify the Vandermonde identity C(m+n, r) = sum of C(m,k)*C(n,r-k) for m=5, n=7, r=4.
  • The hockey stick identity says C(r,r) + C(r+1,r) + ... + C(n,r) = C(n+1, r+1). Verify it for r=2 and n=6.

Quick Quiz

Coding Challenge

Verify Pascal Identity

Write a function called `verifyPascalIdentity` that takes two arguments: `n` (a positive integer) and `k` (an integer with 1 at most k below n). Compute C(n, k) and compare it to C(n-1, k-1) + C(n-1, k). Return true if they are equal, false otherwise. You will need to implement a helper function to compute C(n, k). Use the multiplicative formula: C(n,k) = n*(n-1)*...*(n-k+1) / k! to avoid overflow.

Loading editor...

Real-World Usage

Combinatorial proof techniques appear in surprising places:

  • Algorithm correctness: Proving that a greedy algorithm always finds the optimal solution often involves a bijection between feasible solutions and some structured set.
  • Data structure analysis: Proving that a balanced BST has O(log n) height uses combinatorial arguments about the number of nodes at each level.
  • Coding theory: The number of error-correcting codewords is computed using binomial coefficients. Identities like Vandermonde help analyze code properties.
  • Probability theory: Many probability identities have elegant combinatorial proofs. The symmetry C(n,k) = C(n,n-k) proves that the binomial distribution is symmetric around n/2 when p = 1/2.
  • Machine learning: Combinatorial arguments arise when analyzing the VC dimension (a measure of model complexity) and the number of possible decision boundaries.

Connections