All Euler problems
Project Euler

Investigating Numbers with Few Repeated Digits

How many 18-digit numbers n (without leading zeros) are there such that no digit occurs more than three times in n?

Source sync Apr 19, 2026
Problem #0172
Level Level 07
Solved By 4,415
Languages C++, Python
Answer 227485267000992000
Length 387 words
dynamic_programminglinear_algebradigit_dp

Problem Statement

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

How many \(18\)-digit numbers \(n\) (without leading zeros) are there such that no digit occurs more than three times in \(n\)?

Problem 172: Investigating Numbers with Few Repeated Digits

Mathematical Development

Theorem 1 (Multinomial counting). The number of strings of length LL over the alphabet {0,1,,9}\{0,1,\ldots,9\} in which digit ii appears exactly cic_i times, where i=09ci=L\sum_{i=0}^{9} c_i = L, is the multinomial coefficient

(Lc0,c1,,c9)=L!c0!c1!c9!.\binom{L}{c_0, c_1, \ldots, c_9} = \frac{L!}{c_0!\, c_1!\, \cdots\, c_9!}.

Proof. There are L!L! total orderings of LL labelled positions. For each digit ii, the cic_i positions receiving digit ii are mutually indistinguishable, producing ci!c_i! redundant orderings. Dividing by the product of all such redundancies gives the stated formula. \square

Theorem 2 (Exponential generating function). The total number of length-LL strings over a 10-symbol alphabet with each symbol appearing at most mm times is

T(L,m)=L![xL](k=0mxkk!) ⁣10.T(L, m) = L!\, [x^L] \left(\sum_{k=0}^{m} \frac{x^k}{k!}\right)^{\!10}.

Proof. The exponential generating function (EGF) for a single symbol restricted to at most mm occurrences is g(x)=k=0mxk/k!g(x) = \sum_{k=0}^{m} x^k/k!. Since the ten symbols occupy disjoint subsets of positions, the EGF for the combined structure is g(x)10g(x)^{10} (product formula for labelled combinatorial species). The coefficient [xL][x^L] of the product, multiplied by L!L!, recovers the ordinary count. \square

Lemma 1 (Leading-zero subtraction). Let T(L,m)T(L, \mathbf{m}) denote the number of length-LL strings where digit ii appears at most mim_i times. The count of LL-digit positive integers (no leading zero) with each digit appearing at most mm times is

A(L,m)=T(L,(m,m,,m))T(L1,(m1,m,,m)).A(L,m) = T\bigl(L,\, (m,m,\ldots,m)\bigr) - T\bigl(L-1,\, (m-1,m,\ldots,m)\bigr).

Proof. The strings counted by T(L,m)T(L, \mathbf{m}) include those with a leading zero. A string with leading zero has its first position fixed to 00; the remaining L1L-1 positions form a string with digit 00 appearing at most m1m-1 additional times and all other digits at most mm times. The subtraction removes precisely these invalid strings. \square

Theorem 3 (Sequential digit DP). Define dp[j]\mathrm{dp}[j] as the number of ways to assign values from the digits processed so far to exactly jj of the LL positions. Initialize dp[0]=1\mathrm{dp}[0] = 1. When processing digit ii with maximum frequency mim_i, the update rule is

dp[j+c]+=dp[j](Ljc),c=0,1,,mi.\mathrm{dp}'[j + c] \mathrel{+}= \mathrm{dp}[j] \cdot \binom{L-j}{c}, \qquad c = 0, 1, \ldots, m_i.

After processing all 10 digits, dp[L]\mathrm{dp}[L] equals T(L,m)T(L, \mathbf{m}).

Proof. By induction on the number of digits processed. When digit ii is placed in cc of the LjL - j remaining positions, there are (Ljc)\binom{L-j}{c} ways to choose which positions receive digit ii. The multiplication principle applied across all 10 digits yields dp[L]=cL!ci!\mathrm{dp}[L] = \sum_{\mathbf{c}} \frac{L!}{\prod c_i!} summed over all valid frequency vectors c\mathbf{c} with ci=L\sum c_i = L and cimic_i \leq m_i. This follows because the telescoping product of binomial coefficients satisfies

i=09(Lj<icjci)=L!i=09ci!.\prod_{i=0}^{9} \binom{L - \sum_{j<i} c_j}{c_i} = \frac{L!}{\prod_{i=0}^{9} c_i!}. \quad \square

Editorial

How many 18-digit numbers n (no leading zero) have each digit appearing at most three times? Method: Sequential digit DP using binomial coefficients.

Pseudocode

    dp[0..L] = 0; dp[0] = 1
    For i from 0 to 9:
        dp'[0..L] = 0
        For j from 0 to L:
            If dp[j] == 0 then continue
            For c from 0 to max_freq[i]:
                If j + c > L then stop this loop
                dp'[j + c] += dp[j] * C(L - j, c)
        dp = dp'
    Return dp[L]

T = count_strings(18, [3,3,3,3,3,3,3,3,3,3])
T0 = count_strings(17, [2,3,3,3,3,3,3,3,3,3])
answer = T - T0

Complexity Analysis

  • Time: Each call to count_strings performs 10×(L+1)×(m+1)10 \times (L+1) \times (m+1) operations. For L=18,m=3L = 18, m = 3: 10×19×4=76010 \times 19 \times 4 = 760. A second call with L=17L = 17 adds 10×18×4=72010 \times 18 \times 4 = 720. Total: O(1480)O(1480).
  • Space: O(L)O(L) for the rolling DP array.

Answer

227485267000992000\boxed{227485267000992000}

Code

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

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

/*
 * Problem 172: 18-digit numbers where each digit appears at most 3 times.
 * Sequential digit DP: for each digit, choose how many positions it fills.
 * Answer = T(18, all caps 3) - T(17, digit-0 cap 2, rest cap 3).
 */

long long compute(int L, vector<int>& maxfreq) {
    vector<vector<long long>> C(L + 1, vector<long long>(L + 1, 0));
    for (int i = 0; i <= L; i++) {
        C[i][0] = 1;
        for (int j = 1; j <= i; j++)
            C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
    }

    vector<long long> dp(L + 1, 0);
    dp[0] = 1;

    for (int dig = 0; dig < 10; dig++) {
        vector<long long> ndp(L + 1, 0);
        for (int j = 0; j <= L; j++) {
            if (dp[j] == 0) continue;
            for (int c = 0; c <= maxfreq[dig] && j + c <= L; c++)
                ndp[j + c] += dp[j] * C[L - j][c];
        }
        dp = ndp;
    }
    return dp[L];
}

int main() {
    vector<int> mf_all(10, 3);
    long long T = compute(18, mf_all);

    vector<int> mf_zero(10, 3);
    mf_zero[0] = 2;
    long long T0 = compute(17, mf_zero);

    cout << T - T0 << endl;
    return 0;
}