All Euler problems
Project Euler

Harshad Numbers

A Harshad number is a number divisible by the sum of its digits. A right truncatable Harshad number is a Harshad number such that recursively truncating the last digit always yields a Harshad numbe...

Source sync Apr 19, 2026
Problem #0387
Level Level 06
Solved By 5,305
Languages C++, Python
Answer 696067597313468
Length 441 words
modular_arithmeticnumber_theorysearch

Problem Statement

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

A Harshad or Niven number is a number that is divisible by the sum of its digits.

\(201\) is a Harshad number because it is divisible by \(3\) (the sum of its digits.)

When we truncate the last digit from \(201\), we get \(20\), which is a Harshad number.

When we truncate the last digit from \(20\), we get \(2\), which is also a Harshad number.

Let’s call a Harshad number that, while recursively truncating the last digit, always results in a Harshad number a right truncatable Harshad number.

Also:

\(201/3=67\) which is prime.

Let’s call a Harshad number that, when divided by the sum of its digits, results in a prime a strong Harshad number

Now take the number \(2011\) which is prime.

When we truncate the last digit from it we get \(201\), a strong Harshad number that is also right truncatable.

Let’s call such primes strong, right truncatable Harshad primes.

You are given that the sum of the strong, right truncatable Harshad primes less than \(10000\) is \(90619\).

Find the sum of the strong, right truncatable Harshad primes less than \(10^{14}\).

Problem 387: Harshad Numbers

Mathematical Analysis

The key observation is that right truncatable Harshad numbers (RTHN) can be built incrementally. If nn is an RTHN with digit sum ss, then 10n+d10n + d (for digit d{0,,9}d \in \{0,\dots,9\}) is an RTHN if and only if (s+d)(10n+d)(s+d) \mid (10n+d).

The algorithm proceeds by breadth-first generation of all RTHN up to 101310^{13} (since appending one more digit to get the prime can reach up to 1014110^{14} - 1). At each RTHN, we check whether it is strong (i.e., n/s(n)n/s(n) is prime). For each strong RTHN, we append digits 1,3,7,91, 3, 7, 9 (the only digits that can make the result prime) and test primality.

Derivation / Algorithm

  1. Seed: Single-digit numbers 1,2,,91, 2, \dots, 9 are all RTHN (each is trivially divisible by itself).
  2. Expand: For each RTHN nn with digit sum ss and n<1013n < 10^{13}, try appending each digit d{0,,9}d \in \{0,\dots,9\}. If (s+d)(10n+d)(s + d) \mid (10n + d), then 10n+d10n + d is a new RTHN with digit sum s+ds + d.
  3. Check strong: For each RTHN nn, if n/s(n)n / s(n) is prime, mark nn as a strong RTHN.
  4. Collect primes: For each strong RTHN nn (with n<1013n < 10^{13}), try p=10n+dp = 10n + d for d{1,3,7,9}d \in \{1, 3, 7, 9\}. If p<1014p < 10^{14} and pp is prime, add pp to the answer.

Proof of Correctness

  • Completeness: Every RTHN of kk digits has an RTHN prefix of k1k-1 digits, so the BFS from single-digit seeds generates all RTHN.
  • Primality of strong RTHN primes: We only count a prime pp if its prefix p/10\lfloor p/10 \rfloor is simultaneously right truncatable Harshad and strong Harshad, matching the problem definition exactly.
  • Verification: The algorithm yields a sum of 90619 for the limit 10410^4, matching the given test case.

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

Complexity Analysis

  • Time: The number of RTHN up to 101310^{13} is relatively small (on the order of tens of thousands). For each, we perform a constant number of divisibility checks and at most 4 primality tests. Primality testing of numbers up to 101410^{14} via deterministic Miller-Rabin with appropriate witnesses runs in O(log2n)O(\log^2 n). Overall: effectively O(Rlog2N)O(R \cdot \log^2 N) where RR is the count of RTHN and N=1014N = 10^{14}.
  • Space: O(R)O(R) to store the current frontier of RTHN.

Answer

696067597313468\boxed{696067597313468}

Code

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

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

typedef long long ll;
typedef unsigned long long ull;

// Modular exponentiation: a^e mod m (handles large intermediates via __int128)
ll mod_pow(ll base, ll exp, ll mod) {
    ll result = 1;
    base %= mod;
    while (exp > 0) {
        if (exp & 1)
            result = (__int128)result * base % mod;
        base = (__int128)base * base % mod;
        exp >>= 1;
    }
    return result;
}

// Deterministic Miller-Rabin for n < 3.317e14
bool is_prime(ll n) {
    if (n < 2) return false;
    if (n < 4) return true;
    if (n % 2 == 0 || n % 3 == 0) return false;
    ll d = n - 1;
    int r = 0;
    while (d % 2 == 0) { d /= 2; r++; }
    for (ll a : {2, 3, 5, 7, 11, 13, 17}) {
        if (a >= n) continue;
        ll x = mod_pow(a, d, n);
        if (x == 1 || x == n - 1) continue;
        bool composite = true;
        for (int i = 0; i < r - 1; i++) {
            x = (__int128)x * x % n;
            if (x == n - 1) { composite = false; break; }
        }
        if (composite) return false;
    }
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    const ll LIMIT = 100000000000000LL; // 10^14
    const ll PREFIX_LIMIT = LIMIT / 10;

    ll total = 0;
    // (number, digit_sum)
    vector<pair<ll, int>> frontier;
    for (int d = 1; d <= 9; d++)
        frontier.push_back({d, d});

    while (!frontier.empty()) {
        vector<pair<ll, int>> next_frontier;
        for (auto& [n, s] : frontier) {
            // Check if strong Harshad: n/s is prime
            if (n % s == 0 && is_prime(n / s)) {
                for (int d : {1, 3, 7, 9}) {
                    ll candidate = 10 * n + d;
                    if (candidate < LIMIT && is_prime(candidate))
                        total += candidate;
                }
            }
            // Expand: append digits 0..9
            for (int d = 0; d <= 9; d++) {
                ll new_n = 10 * n + d;
                int new_s = s + d;
                if (new_n < PREFIX_LIMIT && new_s > 0 && new_n % new_s == 0)
                    next_frontier.push_back({new_n, new_s});
            }
        }
        frontier = move(next_frontier);
    }

    cout << total << endl;
    return 0;
}