Tim Varley Logo
Tim Varley Systems Engineer
Problem #43 hard

Sub-string Divisibility

The number, 14063572891406357289, is a 00 to 99 pandigital number because it is made up of each of the digits 00 to 99 in some order, but it also has a rather interesting sub-string divisibility property.

Let d1d_1 be the 11st digit, d2d_2 be the 22nd digit, and so on. In this way, we note the following:

  • d2d3d4=406d_2d_3d_4=406 is divisible by 22
  • d3d4d5=063d_3d_4d_5=063 is divisible by 33
  • d4d5d6=635d_4d_5d_6=635 is divisible by 55
  • d5d6d7=357d_5d_6d_7=357 is divisible by 77
  • d6d7d8=572d_6d_7d_8=572 is divisible by 1111
  • d7d8d9=728d_7d_8d_9=728 is divisible by 1313
  • d8d9d10=289d_8d_9d_{10}=289 is divisible by 1717

Find the sum of all 00 to 99 pandigital numbers with this property.

Implementations

cpp
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
long long substring_divisibility() {
std::string digits = "0123456789";
std::sort(digits.begin(), digits.end());
std::vector<int> primes = {2, 3, 5, 7, 11, 13, 17};
long long sum = 0;
do {
bool valid = true;
for (int i = 0; i < 7; i++) {
int num = std::stoi(digits.substr(i + 1, 3));
if (num % primes[i] != 0) {
valid = false;
break;
}
}
if (valid) {
sum += std::stoll(digits);
}
} while (std::next_permutation(digits.begin(), digits.end()));
return sum;
}
#if ! defined UNITTEST_MODE
int main(int argc, char const *argv[]) {
std::cout << substring_divisibility() << std::endl;
}
#endif // UNITTEST_MODE

Solution Notes

Mathematical Background

A pandigital number uses each digit from 0 to 9 exactly once. The problem requires finding all such numbers where specific 3-digit substrings are divisible by given primes.

The substrings and their divisors are:

  • d₂d₃d₄ divisible by 2
  • d₃d₄d₅ divisible by 3
  • d₄d₅d₆ divisible by 5
  • d₅d₆d₇ divisible by 7
  • d₆d₇d₈ divisible by 11
  • d₇d₈d₉ divisible by 13
  • d₈d₉d₁₀ divisible by 17

Algorithm Analysis

The solution generates all permutations of digits 0-9 and checks each against the divisibility conditions. Since 10! = 3,628,800 permutations, brute force is feasible.

For each permutation, convert to string and check seven 3-digit numbers for divisibility. Early termination in some implementations (like backtracking in JavaScript) prunes invalid branches.

Performance Analysis

  • Time Complexity: O(10! × 7) ≈ 25 million operations, very fast on modern hardware
  • Space Complexity: O(1) for most implementations, O(10!) for storing all permutations in some
  • Execution Time: <1 second typically
  • Scalability: Fixed at 10 digits, no scaling concerns

Key Insights

  • Divisibility by 2 and 5 can be checked by last digit

  • Divisibility by 3 and 9 by digit sum

  • Higher primes require full number checking

  • Backtracking reduces permutations significantly

  • No leading zero constraint for the number itself

Educational Value

This problem demonstrates:

  • Permutation generation algorithms

  • Modular arithmetic and divisibility rules

  • Backtracking optimization techniques

  • Performance trade-offs between memory and computation

  • The intersection of combinatorics and number theory