All Euler problems
Project Euler

The Prime Factorisation of Binomial Coefficients

The binomial coefficient C(10, 3) = 120 has prime factorisation 2^3 x 3 x 5, so the sum of the terms in its prime factorisation is 2^3 + 3 + 5 = 16. Find the sum of the terms in the prime factorisa...

Source sync Apr 19, 2026
Problem #0231
Level Level 06
Solved By 6,141
Languages C++, Python
Answer 7526965179680
Length 213 words
number_theorycombinatoricsbrute_force

Problem Statement

This archive keeps the full statement, math, and original media on the page.

The binomial coefficient \(\displaystyle \binom {10} 3 = 120\).

\(120 = 2^3 \times 3 \times 5 = 2 \times 2 \times 2 \times 3 \times 5\), and \(2 + 2 + 2 + 3 + 5 = 14\).

So the sum of the terms in the prime factorisation of \(\displaystyle \binom {10} 3\) is \(14\).

Find the sum of the terms in the prime factorisation of \(\displaystyle \binom {20\,000\,000} {15\,000\,000}\).

Problem 231: The Prime Factorisation of Binomial Coefficients

Mathematical Foundation

Theorem (Legendre’s Formula). For any prime pp and positive integer nn, the pp-adic valuation of n!n! is

vp(n!)=i=1npi=nsp(n)p1v_p(n!) = \sum_{i=1}^{\infty} \left\lfloor \frac{n}{p^i} \right\rfloor = \frac{n - s_p(n)}{p - 1}

where sp(n)s_p(n) denotes the sum of the digits of nn in base pp.

Proof. Among 1,2,,n1, 2, \ldots, n, exactly n/p\lfloor n/p \rfloor are divisible by pp, exactly n/p2\lfloor n/p^2 \rfloor are divisible by p2p^2, and so on. Each multiple of pip^i contributes at least ii factors of pp to n!n!. Counting each factor of pp once yields vp(n!)=i1n/piv_p(n!) = \sum_{i \geq 1} \lfloor n/p^i \rfloor. Writing nn in base pp as n=jdjpjn = \sum_{j} d_j p^j, a telescoping computation gives i1n/pi=(nsp(n))/(p1)\sum_{i \geq 1} \lfloor n/p^i \rfloor = (n - s_p(n))/(p-1). \square

Lemma (Kummer’s Theorem). For primes pp and integers 0kn0 \leq k \leq n, the pp-adic valuation of (nk)\binom{n}{k} equals the number of carries when adding kk and nkn - k in base pp.

Proof. We have vp ⁣((nk))=vp(n!)vp(k!)vp((nk)!)v_p\!\left(\binom{n}{k}\right) = v_p(n!) - v_p(k!) - v_p((n-k)!). Applying Legendre’s formula:

vp ⁣((nk))=(ksp(k))+((nk)sp(nk))(nsp(n))p1=sp(k)+sp(nk)sp(n)p1.v_p\!\left(\binom{n}{k}\right) = \frac{(k - s_p(k)) + ((n-k) - s_p(n-k)) - (n - s_p(n))}{p-1} = \frac{s_p(k) + s_p(n-k) - s_p(n)}{p-1}.

The quantity sp(k)+sp(nk)sp(n)s_p(k) + s_p(n-k) - s_p(n) equals (p1)(p-1) times the number of carries in the base-pp addition k+(nk)=nk + (n-k) = n, since each carry reduces the digit sum by exactly p1p - 1. \square

Corollary. The exponent of prime pp in (nk)\binom{n}{k} is

ep=i=1logpn(npikpinkpi).e_p = \sum_{i=1}^{\lfloor \log_p n \rfloor} \left( \left\lfloor \frac{n}{p^i} \right\rfloor - \left\lfloor \frac{k}{p^i} \right\rfloor - \left\lfloor \frac{n-k}{p^i} \right\rfloor \right).

The desired answer is S=pn,p primeeppS = \sum_{p \leq n,\, p\text{ prime}} e_p \cdot p.

Editorial

We iterate over p in primes. We first generate the primes required by the search, then enumerate the admissible combinations and retain only the values that satisfy the final test.

Pseudocode

    primes = sieve_of_eratosthenes(n)
    S = 0
    for p in primes:
        e = 0
        power = p
        While power <= n:
            e += floor(n / power) - floor(k / power) - floor((n - k) / power)
            power *= p
        S += e * p
    Return S

Complexity Analysis

  • Time: O(nloglogn)O(n \log \log n) for the Sieve of Eratosthenes, plus O(π(n)log2n)O(\pi(n) \cdot \log_2 n) for computing exponents across all primes. Total: O(nloglogn)O(n \log \log n).
  • Space: O(n)O(n) for the sieve array.

Answer

7526965179680\boxed{7526965179680}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_231/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    const int N = 20000000;
    const int K = 15000000;
    const int M = N - K; // 5000000

    // Sieve of Eratosthenes
    vector<bool> is_prime(N + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; (long long)i * i <= N; i++) {
        if (is_prime[i]) {
            for (int j = i * i; j <= N; j += i)
                is_prime[j] = false;
        }
    }

    // For each prime, compute exponent in C(N, K) using Legendre's formula
    long long answer = 0;
    for (int p = 2; p <= N; p++) {
        if (!is_prime[p]) continue;
        long long exp_val = 0;
        long long pk = p;
        while (pk <= N) {
            exp_val += N / pk - K / pk - M / pk;
            if (pk > N / p) break; // prevent overflow
            pk *= p;
        }
        answer += exp_val * p;
    }

    cout << answer << endl;
    return 0;
}