Project Euler Problem 290
How many integers 0 le n lt 10^{18} have the property that the sum of the digits of n equals the sum of digits of 137n?
Solution
Answer: 20444710234716473
Let $s(n)$ denote the sum of the decimal digits of $n$.
We seek the number of integers
$$0 \le n < 10^{18}$$
such that
$$s(n)=s(137n).$$
Mathematical analysis
Let
$$n=\sum_{i=0}^{17} d_i 10^i, \qquad 0\le d_i\le 9.$$
We process multiplication by $137$ digit-by-digit from least significant to most significant.
1. Digit-sum behavior under carrying
Suppose at some step we compute
$$137d_i + c_i,$$
where $c_i$ is the incoming carry.
Write
$$137d_i+c_i = 10c_{i+1}+e_i,$$
with $e_i$ the output digit of $137n$.
Then:
$$e_i = (137d_i+c_i)\bmod 10, \qquad c_{i+1}=\left\lfloor \frac{137d_i+c_i}{10}\right\rfloor.$$
The contribution to the digit-sum difference is
$$d_i-e_i.$$
After all 18 digits are processed, some carry remains. Its decimal digits also contribute to the digit sum of $137n$.
Hence
$$s(n)-s(137n) = \sum_{i=0}^{17}(d_i-e_i) - s(c_{18}),$$
where $s(c_{18})$ is the digit sum of the final carry.
We therefore need
$$\sum_{i=0}^{17}(d_i-e_i)=s(c_{18}).$$
This is ideal for digit DP.
2. State compression
At each position we only need:
- the current carry,
- the accumulated difference
$$\Delta=\sum(d_i-e_i).$$
So define:
$$\text{DP}(pos, carry, \Delta)$$
= number of ways to fill digits from position pos onward.
At the end (pos = 18), we accept iff
$$\Delta = s(carry).$$
The carry remains small:
$$137\cdot 9 + \text{carry} < 1400,$$
so the state space is tiny.
Python implementation
from functools import lru_cache
LENGTH = 18
MULTIPLIER = 137
@lru_cache(None)
def dp(pos, carry, diff):
"""
pos : current digit position (0 = least significant)
carry : carry entering this position
diff : accumulated value of sum(d_i - e_i)
"""
# All 18 digits processed
if pos == LENGTH:
# Remaining carry contributes digits to 137n
carry_digit_sum = 0
c = carry
while c > 0:
carry_digit_sum += c % 10
c //= 10
# Need total digit sums to match
return 1 if diff == carry_digit_sum else 0
total = 0
# Choose next digit of n
for d in range(10):
value = MULTIPLIER * d + carry
# Output digit of 137n
out_digit = value % 10
# Next carry
next_carry = value // 10
# Update digit-sum difference
next_diff = diff + d - out_digit
total += dp(pos + 1, next_carry, next_diff)
return total
answer = dp(0, 0, 0)
print(answer)
Code walkthrough
Constants
LENGTH = 18
MULTIPLIER = 137
We consider all integers below $10^{18}$, so exactly 18 decimal positions.
Memoized DP
@lru_cache(None)
def dp(pos, carry, diff):
The DP state stores:
pos: current digit index,carry: carry from previous multiplication step,diff: accumulated difference
$$\sum(d_i-e_i).$$
Base case
if pos == LENGTH:
All digits have been processed.
The remaining carry still contributes decimal digits to $137n$, so we compute:
carry_digit_sum
and accept iff
diff == carry_digit_sum
which is exactly equivalent to
$$s(n)=s(137n).$$
Transition
For every possible decimal digit:
for d in range(10):
we compute:
value = 137 * d + carry
The resulting output digit is:
out_digit = value % 10
and the next carry is:
next_carry = value // 10
The digit-sum difference changes by:
d - out_digit
so we recurse.
Small sanity check
Take $n=1$:
$$137n = 137.$$
Digit sums:
$$s(1)=1,\qquad s(137)=1+3+7=11.$$
Not equal.
Our DP rejects this because the accumulated difference is not balanced by the final carry digits.
Final verification
The count should be large:
- there are $10^{18}$ candidates total,
- the digit-sum constraint is restrictive but not extremely rare,
- the final answer around $2\times 10^{16}$ is plausible.
The DP state space is tiny and exhaustive, so the result is exact.
Answer: 20444710234716473