All Euler problems
Project Euler

Reachable Numbers

Consider the digit string "123456789." By partitioning these digits into contiguous groups (forming multi-digit numbers by concatenation), inserting binary operators +, -, x, / between groups, and...

Source sync Apr 19, 2026
Problem #0259
Level Level 11
Solved By 1,740
Languages C++, Python
Answer 20101196798
Length 456 words
dynamic_programminggeometrysequence

Problem Statement

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

A positive integer will be called reachable if it can result from an arithmetic expression obeying the following rules:

  • Uses the digits \(1\) through \(9\), in that order and exactly once each.

  • Any successive digits can be concatenated (for example, using the digits \(2\), \(3\) and \(4\) we obtain the number \(234\)).

  • Only the four usual binary arithmetic operations (addition, subtraction, multiplication and division) are allowed.

  • Each operation can be used any number of times, or not at all.

  • Unary minus is not allowed.

  • Any number of (possibly nested) parentheses may be used to define the order of operations.

For example, \(42\) is reachable, since \((1 / 23) \times ((4 \times 5) - 6) \times (78 - 9) = 42\).

What is the sum of all positive reachable integers?

Problem 259: Reachable Numbers

Mathematical Foundation

Definition. For indices 1ij91 \le i \le j \le 9, let R(i,j)QR(i,j) \subseteq \mathbb{Q} be the set of all rational numbers obtainable from the contiguous digit substring didi+1djd_i d_{i+1} \cdots d_j (where dk=kd_k = k) by partitioning, operator insertion, and arbitrary parenthesization.

Lemma 1 (Base Case). R(i,j)R(i,j) always contains the concatenated integer didi+1dj\overline{d_i d_{i+1} \cdots d_j}. In particular, R(i,i)={i}R(i,i) = \{i\} is the singleton containing digit ii.

Proof. The trivial partition (no splits) produces the concatenated number. For a single digit, no operators can be inserted, so the only value is the digit itself. \square

Theorem 1 (Interval DP Recurrence). For j>ij > i, the set R(i,j)R(i,j) satisfies:

R(i,j)={didj}k=ij1{ab:aR(i,k),  bR(k+1,j),  {+,,×,÷},  (b0 if =÷)}.R(i,j) = \left\{\overline{d_i \cdots d_j}\right\} \cup \bigcup_{k=i}^{j-1} \left\{a \circ b : a \in R(i,k),\; b \in R(k+1,j),\; \circ \in \{+,-,\times,\div\},\; (b \ne 0 \text{ if } \circ = \div)\right\}.

Proof. Any expression over di,,djd_i, \ldots, d_j either treats all digits as one concatenated number (no operator at the top level) or has a “last” binary operator \circ applied between some left part didkd_i \cdots d_k and right part dk+1djd_{k+1} \cdots d_j. The left and right subexpressions can independently be any value in R(i,k)R(i,k) and R(k+1,j)R(k+1,j) respectively, by induction. The split point kk ranges over all valid positions. \square

Theorem 2 (Correctness of Interval DP). The recurrence in Theorem 1 produces exactly the set of all obtainable values. That is, every binary expression tree over the ordered leaves di,,djd_i, \ldots, d_j (with contiguous groups at the leaves) corresponds to some choice of split point and recursive subexpressions.

Proof. By structural induction on expression trees. A tree with one leaf corresponds to the base case. A tree with root operator \circ, left subtree over didkd_i \cdots d_k, and right subtree over dk+1djd_{k+1} \cdots d_j is captured by the union in the recurrence. Since every expression tree has a unique root split, the correspondence is exhaustive. \square

Lemma 2 (Exact Arithmetic). Division may produce non-integer rationals (e.g., 1/21/2). Using exact rational arithmetic (representing each value as a fraction p/qp/q in lowest terms) ensures no precision loss.

Proof. All inputs are integers, and closure of Q\mathbb{Q} under {+,,×,÷}\{+,-,\times,\div\} (excluding division by zero) ensures all intermediate and final values are rational. \square

Editorial

From the string “123456789”, insert +, -, *, / between groups of consecutive digits (with arbitrary parenthesization) to produce values. Find the sum of all positive integers reachable. Method: Interval DP with exact rational arithmetic (fractions). R(i,j) = set of all rationals from digits i..j. We digits: d[1]=1, d[2]=2, …, d[9]=9. We then compute R(i,j) for all 1 <= i <= j <= 9 using interval DP. Finally, base case.

Pseudocode

Digits: d[1]=1, d[2]=2, ..., d[9]=9
Compute R(i,j) for all 1 <= i <= j <= 9 using interval DP
Base case
Fill DP table by increasing interval length
Extract positive integers from R[1][9]

Complexity Analysis

  • Time: There are (92)+9=45\binom{9}{2} + 9 = 45 subproblems. Each R(i,j)|R(i,j)| is bounded empirically by a few thousand. For the full interval R(1,9)R(1,9), the set size is at most 105\sim 10^5. The total work is O ⁣(ij(ji)R(i,)R(,j))O\!\left(\sum_{i \le j} (j-i) \cdot |R(i,\cdot)| \cdot |R(\cdot,j)|\right), which is bounded and completes in under one second.
  • Space: O ⁣(ijR(i,j))O\!\left(\sum_{i \le j} |R(i,j)|\right), on the order of 10510^5 rational numbers.

Answer

20101196798\boxed{20101196798}

Code

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

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

/*
 * Problem 259: Reachable Numbers
 *
 * From the string "123456789", by concatenating adjacent digits and inserting
 * +, -, *, / between groups (with arbitrary parenthesization), find the sum
 * of all positive integers that can be produced.
 *
 * Method: Interval DP over substrings. R(i,j) = set of all rationals
 * achievable from digits i..j. Use exact fractions (p/q in lowest terms).
 *
 * Answer: 20101196798
 */

typedef pair<long long, long long> Frac; // (numerator, denominator), always reduced, denom > 0

long long gcd_abs(long long a, long long b) {
    a = abs(a); b = abs(b);
    while (b) { a %= b; swap(a, b); }
    return a;
}

Frac make_frac(long long p, long long q) {
    if (q == 0) return {0, 0}; // invalid
    if (p == 0) return {0, 1};
    if (q < 0) { p = -p; q = -q; }
    long long g = gcd_abs(p, q);
    return {p / g, q / g};
}

Frac add(Frac a, Frac b) { return make_frac(a.first * b.second + b.first * a.second, a.second * b.second); }
Frac sub(Frac a, Frac b) { return make_frac(a.first * b.second - b.first * a.second, a.second * b.second); }
Frac mul(Frac a, Frac b) { return make_frac(a.first * b.first, a.second * b.second); }
Frac divf(Frac a, Frac b) {
    if (b.first == 0) return {0, 0};
    return make_frac(a.first * b.second, a.second * b.first);
}

set<Frac> dp[10][10]; // dp[i][j] for digits i..j (1-indexed)
bool computed[10][10];

long long concat_num(int i, int j) {
    long long num = 0;
    for (int k = i; k <= j; k++) num = num * 10 + k;
    return num;
}

void solve(int i, int j) {
    if (computed[i][j]) return;
    computed[i][j] = true;

    // Base: concatenated number
    dp[i][j].insert(make_frac(concat_num(i, j), 1));

    // Split
    for (int k = i; k < j; k++) {
        solve(i, k);
        solve(k + 1, j);
        for (auto& a : dp[i][k]) {
            for (auto& b : dp[k+1][j]) {
                dp[i][j].insert(add(a, b));
                dp[i][j].insert(sub(a, b));
                dp[i][j].insert(mul(a, b));
                Frac d = divf(a, b);
                if (d.second != 0) dp[i][j].insert(d);
            }
        }
    }
}

int main() {
    memset(computed, false, sizeof(computed));
    solve(1, 9);

    long long ans = 0;
    for (auto& f : dp[1][9]) {
        if (f.second == 1 && f.first > 0) {
            ans += f.first;
        }
    }
    cout << ans << endl;
    return 0;
}