All Euler problems
Project Euler

Step Numbers

Consider the number 45656. It can be seen that each pair of consecutive digits differs by one (|4-5| = |5-6| = |6-5| = |5-6| = 1). A number where each pair of consecutive digits differs by exactly...

Source sync Apr 19, 2026
Problem #0178
Level Level 07
Solved By 3,969
Languages C++, Python
Answer 126461847755
Length 295 words
dynamic_programmingoptimizationdigit_dp

Problem Statement

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

Consider the number \(45656\).

It can be seen that each pair of consecutive digits of \(45656\) has a difference of one.

A number for which every pair of consecutive digits has a difference of one is called a step number.

A pandigital number contains every decimal digit from \(0\) to \(9\) at least once.

How many pandigital step numbers less than \(10^{40}\) are there?

Problem 178: Step Numbers

Mathematical Analysis

Dynamic Programming Approach

We define a DP state:

  • dp[n][d][mask] = number of n-digit step numbers ending in digit d, where mask is a bitmask indicating which digits 0-9 have appeared.

Transitions

From state (n, d, mask), we can extend to:

  • (n+1, d-1, mask | (1 << (d-1))) if d >= 1
  • (n+1, d+1, mask | (1 << (d+1))) if d <= 8

Base Case

For n = 1: dp[1][d][1 << d] = 1 for d = 1, …, 9 (no leading zeros).

Answer

0\boxed{0} answer=n=140d=09dp[n][d][1023]\text{answer} = \sum_{n=1}^{40} \sum_{d=0}^{9} dp[n][d][1023]

where 1023=21011023 = 2^{10} - 1 represents all digits 0-9 being present.

Optimization

Since we need at least 10 digits (to include all 0-9), and each step changes by 1, we need at least 9 steps from 0 to 9. So the minimum number of digits is 10.

The mask has 210=10242^{10} = 1024 states, digits have 10 states, and length goes up to 40. Total states: 40×10×1024=40960040 \times 10 \times 1024 = 409600, which is very manageable.

Correctness

Theorem. The method described above computes exactly the quantity requested in the problem statement.

Proof. The preceding analysis identifies the admissible objects and derives the formula, recurrence, or exhaustive search carried out by the algorithm. The computation evaluates exactly that specification, so every valid contribution is included once and no invalid contribution is counted. Therefore the returned value is the required answer. \square

Answer

126461847755\boxed{126461847755}

Complexity

Time: O(N×D×2D)=O(40×10×1024)O(N \times D \times 2^D) = O(40 \times 10 \times 1024), essentially O(1)O(1).

Space: O(D×2D)O(D \times 2^D) with rolling array optimization.

Code

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

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

// Problem 178: Step Numbers
// Count pandigital step numbers (containing all digits 0-9) with up to 40 digits.
// DP: dp[d][mask] = count of step numbers ending in digit d with digit set mask.

int main() {
    const int MAXN = 40;
    const int FULL = (1 << 10) - 1;  // 1023

    // dp[d][mask]
    long long dp[10][1024] = {};
    long long ndp[10][1024] = {};

    // Base case: 1-digit numbers (d = 1..9, no leading zero)
    for (int d = 1; d <= 9; d++) {
        dp[d][1 << d] = 1;
    }

    long long answer = 0;

    // Check if 1-digit numbers are pandigital (they can't be)
    for (int d = 0; d <= 9; d++) {
        answer += dp[d][FULL];
    }

    // Extend from length n to n+1
    for (int n = 1; n < MAXN; n++) {
        memset(ndp, 0, sizeof(ndp));
        for (int d = 0; d <= 9; d++) {
            for (int mask = 0; mask <= FULL; mask++) {
                if (dp[d][mask] == 0) continue;
                long long val = dp[d][mask];
                if (d >= 1) {
                    ndp[d-1][mask | (1 << (d-1))] += val;
                }
                if (d <= 8) {
                    ndp[d+1][mask | (1 << (d+1))] += val;
                }
            }
        }
        memcpy(dp, ndp, sizeof(dp));

        // Count pandigital step numbers of length n+1
        for (int d = 0; d <= 9; d++) {
            answer += dp[d][FULL];
        }
    }

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