Sub-string Divisibility
Let d_1 d_2 d_3... d_10 be a 0 -to- 9 pandigital number (a permutation of the digits {0,1,...,9}). We require the following sub-string divisibility conditions: | Substring | Divisor | |-----------|...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
The number, \(1406357289\), is a \(0\) to \(9\) pandigital number because it is made up of each of the digits \(0\) to \(9\) in some order, but it also has a rather interesting sub-string divisibility property.
Let \(d_1\) be the \(1^{st}\) digit, \(d_2\) be the \(2^{nd}\) digit, and so on. In this way, we note the following:
-
\(d_2d_3d_4=406\) is divisible by \(2\)
-
\(d_3d_4d_5=063\) is divisible by \(3\)
-
\(d_4d_5d_6=635\) is divisible by \(5\)
-
\(d_5d_6d_7=357\) is divisible by \(7\)
-
\(d_6d_7d_8=572\) is divisible by \(11\)
-
\(d_7d_8d_9=728\) is divisible by \(13\)
-
\(d_8d_9d_{10}=289\) is divisible by \(17\)
Find the sum of all \(0\) to \(9\) pandigital numbers with this property.
Problem 43: Sub-string Divisibility
Mathematical Development
Definitions
Definition 1. For a sequence of digits , the three-digit substring value is .
Definition 2. Let denote the first seven primes. The substring divisibility property requires for each .
Theoretical Development
Lemma 1 (Parity of ). The digit must be even, i.e., .
Proof. The condition requires . Since and are both even, we need .
Lemma 2 (Constraint on ). We have .
Proof. The condition requires . Since , we need , so .
Lemma 3 (Divisibility by 3). The condition is equivalent to .
Proof. Since and , we have .
Lemma 4 (Overlapping constraint propagation). Each consecutive pair of divisibility conditions shares two digits. Specifically, and share digits and . This overlap enables efficient right-to-left construction: once and are fixed, only the new digit (or ) must be determined.
Proof. Immediate from the definition of overlapping substrings.
Theorem 1 (Exhaustive enumeration). There are exactly six -to- pandigital numbers satisfying the substring divisibility property:
Proof. We construct all solutions by building digit sequences from right to left, exploiting the cascading constraints.
Step 1. Enumerate all values of such that is a multiple of with pairwise distinct digits from . There are multiples of in ; after filtering for distinct digits, at most candidates remain.
Step 2. For each valid triple, extend to : choose an unused digit such that .
Step 3. Extend to : choose unused with . By Lemma 2, , drastically reducing candidates.
Step 4. Extend to : choose unused with .
Step 5. Extend to : choose unused with . By Lemma 1, must be even.
Step 6. Extend to : choose unused with (equivalently, by Lemma 3).
Step 7. Extend to : choose unused with . Since is even (already guaranteed by construction), any unused digit works for .
Step 8. Assign the sole remaining digit to .
This exhaustive search with constraint propagation yields exactly six solutions. Their sum is:
The construction is complete in the sense that every digit assignment is tested at each step, and all constraints are verified. No valid pandigital number can be missed.
Editorial
We construct admissible pandigital numbers from right to left, using the overlap between consecutive three-digit divisibility conditions. The search is seeded with distinct-digit multiples of for the block , and each subsequent stage prepends one unused digit that makes the new leading three-digit block divisible by and , respectively. Once all divisibility constraints have been enforced, the unique remaining digit becomes , and the resulting pandigital numbers are summed.
Pseudocode
Algorithm: Pandigital Numbers with Substring Divisibility
Require: The decimal digits 0 through 9.
Ensure: The sum of all 0-to-9 pandigital numbers satisfying the prescribed divisibility conditions.
1: Initialize the search with all distinct-digit three-digit blocks divisible by 17, interpreted as suffixes d_8d_9d_10.
2: For each divisor in the sequence 13, 11, 7, 5, 3, 2 do:
3: Extend every current suffix by prepending a digit d so that the new leading three-digit block is divisible by the current divisor and all digits remain distinct.
4: After the last extension, prepend the unique missing digit to each 9-digit tail to obtain a full pandigital number.
5: Return the sum of all numbers constructed in this way.
Complexity Analysis
Proposition (Time complexity). The algorithm runs in time where is the total number of partial candidates explored across all steps. Empirically, due to the cascading divisibility constraints.
Proof. At each of the 7 extension steps, for each surviving candidate, we try at most 10 digit choices and perform an divisibility check. The key observation is that the constraints are highly restrictive: divisibility by 17 (Step 1) admits at most 53 triples, and each subsequent step eliminates most extensions. The total number of candidates explored is bounded by a small constant (empirically, on the order of 100). This is a dramatic improvement over the naive brute-force enumeration.
Proposition (Space complexity). for storing the candidate list, where is bounded by the number of surviving partial assignments.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
// Right-to-left construction with constraint propagation.
// Seed with multiples of 17, extend through 13, 11, 7, 5, 3, 2.
int primes[] = {17, 13, 11, 7, 5, 3, 2};
// Each candidate: (digit sequence, bitmask of used digits)
vector<pair<vector<int>, int>> candidates;
// Step 1: seed with 3-digit multiples of 17 with distinct digits
for (int m = 17; m < 1000; m += 17) {
int d8 = m / 100, d9 = (m / 10) % 10, d10 = m % 10;
if (d8 != d9 && d8 != d10 && d9 != d10) {
int mask = (1 << d8) | (1 << d9) | (1 << d10);
candidates.push_back({{d8, d9, d10}, mask});
}
}
// Steps 2-7: extend leftward
for (int pi = 1; pi < 7; pi++) {
int p = primes[pi];
vector<pair<vector<int>, int>> next;
for (auto& [seq, mask] : candidates) {
for (int d = 0; d <= 9; d++) {
if (mask & (1 << d)) continue;
int val = 100 * d + 10 * seq[0] + seq[1];
if (val % p == 0) {
vector<int> new_seq = {d};
new_seq.insert(new_seq.end(), seq.begin(), seq.end());
next.push_back({new_seq, mask | (1 << d)});
}
}
}
candidates = next;
}
// Step 8: assign remaining digit as d1
long long total = 0;
for (auto& [seq, mask] : candidates) {
for (int d = 0; d <= 9; d++) {
if (!(mask & (1 << d))) {
long long num = d;
for (int x : seq) num = num * 10 + x;
total += num;
}
}
}
cout << total << endl;
return 0;
}
def solve():
"""Find the sum of all 0-9 pandigital numbers with the sub-string
divisibility property.
Construction proceeds right-to-left, seeding with multiples of 17
and extending leftward through divisors 13, 11, 7, 5, 3, 2.
"""
primes = [17, 13, 11, 7, 5, 3, 2]
# Seed: all 3-digit multiples of 17 with distinct digits
candidates = []
for m in range(17, 1000, 17):
d8, d9, d10 = m // 100, (m // 10) % 10, m % 10
if len({d8, d9, d10}) == 3:
candidates.append(([d8, d9, d10], {d8, d9, d10}))
# Extend leftward through each remaining prime divisor
for p in primes[1:]:
new_candidates = []
for seq, used in candidates:
for d in range(10):
if d not in used:
if (100 * d + 10 * seq[0] + seq[1]) % p == 0:
new_candidates.append(([d] + seq, used | {d}))
candidates = new_candidates
# Assign remaining digit as d1 and compute sum
total = 0
for seq, used in candidates:
d1 = (set(range(10)) - used).pop()
total += int(''.join(map(str, [d1] + seq)))
print(total)
solve()