Project Euler Problem 387
A Harshad or Niven number is a number that is divisible by the sum of its digits.
Solution
Answer: 696067597313468
We need primes $p<10^{14}$ such that:
- $p$ is prime.
- Removing the last digit gives a number $n$ which is:
- Harshad,
- right truncatable Harshad,
- and strong ($n/\text{digitSum}(n)$ is prime).
The key is that brute force over all numbers below $10^{14}$ is impossible.
Instead, we generate only right truncatable Harshad numbers recursively.
Mathematical analysis
1. Harshad numbers
A number $n$ is Harshad if
$$\text{digitSum}(n)\mid n.$$
Example:
$$201,\qquad 2+0+1=3,\qquad 201\equiv 0\pmod 3.$$
2. Right truncatable Harshad numbers
A number is right truncatable Harshad if:
- it is Harshad,
- removing the last digit repeatedly always leaves another Harshad number.
Example:
$$201 \to 20 \to 2$$
and all are Harshad.
This recursive definition suggests a recursive generation process.
If $n$ is right truncatable Harshad, then every child
$$10n+d,\qquad d\in{0,\dots,9}$$
can be tested directly.
3. Strong Harshad numbers
A Harshad number $n$ is strong if
$$\frac{n}{\text{digitSum}(n)}$$
is prime.
For example:
$$201/3=67$$
and $67$ is prime.
4. Strong right truncatable Harshad primes
A prime $p$ is desired if:
- $p$ itself is prime,
- truncating the last digit gives a strong right truncatable Harshad number.
So if
$$p = 10n+d,$$
then:
- $n$ must be strong and right truncatable Harshad,
- $d\in{1,3,7,9}$ (except small primes),
- $p$ must be prime.
Efficient algorithm
We recursively build all right truncatable Harshad numbers below $10^{13}$.
Why $10^{13}$?
Because appending one digit produces primes below $10^{14}$.
For each generated Harshad number $n$:
- compute digit sum $s$,
- check $n \bmod s = 0$,
- recurse on all children $10n+d$.
Additionally:
- if $n/s$ is prime, then $n$ is strong,
- append digits $1,3,7,9$,
- test resulting numbers for primality.
The search tree is tiny compared with all $10^{14}$ integers.
Python implementation
from math import isqrt
LIMIT = 10**14
# ---------------------------------------------------------
# Deterministic primality test for numbers < 1e14
# ---------------------------------------------------------
def is_prime(n):
if n < 2:
return False
small_primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
for p in small_primes:
if n == p:
return True
if n % p == 0:
return False
r = isqrt(n)
f = 31
step = 6
while f <= r:
if n % f == 0:
return False
f += step
step = 6 - step
return True
total = 0
# ---------------------------------------------------------
# DFS generation of right truncatable Harshad numbers
# ---------------------------------------------------------
def dfs(n, digit_sum):
global total
# n is already guaranteed Harshad here
# -----------------------------------------------------
# Check whether n is strong
# -----------------------------------------------------
quotient = n // digit_sum
if is_prime(quotient):
# Append one digit and test primality
for d in (1, 3, 7, 9):
p = 10 * n + d
if p < LIMIT and is_prime(p):
total += p
# -----------------------------------------------------
# Extend to longer Harshad numbers
# -----------------------------------------------------
for d in range(10):
nxt = 10 * n + d
if nxt >= LIMIT // 10:
continue
s = digit_sum + d
if nxt % s == 0:
dfs(nxt, s)
# ---------------------------------------------------------
# Start with 1-digit Harshad numbers
# ---------------------------------------------------------
for i in range(1, 10):
dfs(i, i)
print(total)
Code walkthrough
Primality testing
def is_prime(n):
We need many primality tests, so this must be efficient.
We first eliminate:
- numbers $<2$,
- divisibility by small primes.
Then we test remaining odd candidates up to $\sqrt n$.
This is fast enough because the search space is relatively small.
DFS generation
def dfs(n, digit_sum):
Parameters:
n= current right truncatable Harshad number,digit_sum= sum of digits ofn.
We already know n is Harshad.
Strong check
quotient = n // digit_sum
If quotient is prime, then n is strong.
Generating candidate primes
for d in (1,3,7,9):
Any prime larger than $5$ must end in one of these digits.
We append the digit and test primality.
If prime:
total += p
Extending the recursion
nxt = 10*n + d
We try all possible appended digits.
The new digit sum is:
s = digit_sum + d
The child is Harshad iff:
nxt % s == 0
If true, recurse.
Verification on the small example
The problem states:
the sum of strong, right truncatable Harshad primes below 10000 is 90619.
Running the same program with:
LIMIT = 10000
produces:
$$90619$$
which confirms correctness.
Final verification
The recursion only generates valid right truncatable Harshad numbers, so no irrelevant numbers are explored.
Every candidate prime is explicitly primality-tested.
The final total is positive and of the expected magnitude (about $10^{14}$ scale summed over many primes).
The known correct Project Euler result is:
Answer: 696067597313468