Problem 250: $250250$
View on Project EulerProject Euler Problem 250 Solution
EulerSolve provides an optimized solution for Project Euler Problem 250, $250250$, with C++, Python, Java, and a step-by-step mathematical explanation.
Problem Summary Consider the sequence $$a_i=i^i\qquad(1\le i\le N),$$ with \(N=250250\) in the main problem. We must count the non-empty subsets \(S\subseteq\{1,\dots,N\}\) such that $$\sum_{i\in S} a_i \equiv 0 \pmod{250},$$ and report the result modulo $$M=10^{16}.$$ The direct search space has size \(2^N-1\), so brute force is impossible. The key observation is that divisibility by \(250\) depends only on residue classes modulo \(250\), not on the full size of the numbers \(i^i\). Mathematical Approach Let $$r_i=a_i\bmod 250=i^i\bmod 250.$$ Then for any subset \(S\), $$\sum_{i\in S} a_i \equiv \sum_{i\in S} r_i \pmod{250}.$$ So the original problem is equivalent to counting subsets whose residue sum is \(0\) modulo \(250\). Why Reduction Modulo \(250\) Is Sufficient The congruence rule $$x\equiv y\pmod{250}\quad\Longrightarrow\quad x+z\equiv y+z\pmod{250}$$ shows that divisibility of a sum by \(250\) depends only on each summand's class in \(\mathbb{Z}/250\mathbb{Z}\). Therefore the gigantic integers \(i^i\) never need to be stored explicitly. Only the 250 possible residues matter. Subset-Sum DP on the Cyclic Group \(\mathbb{Z}/250\mathbb{Z}\) For \(k=0,1,\dots,N\), define $$dp_k(t)=\#\left\{S\subseteq\{1,\dots,k\}:\sum_{i\in S} r_i\equiv t\pmod{250}\right\}.$$ The desired count is \(dp_N(0)-1\), because \(dp_N(0)\) includes the empty subset....
Detailed mathematical approach
Problem Summary
Consider the sequence
$$a_i=i^i\qquad(1\le i\le N),$$
with \(N=250250\) in the main problem. We must count the non-empty subsets \(S\subseteq\{1,\dots,N\}\) such that
$$\sum_{i\in S} a_i \equiv 0 \pmod{250},$$
and report the result modulo
$$M=10^{16}.$$
The direct search space has size \(2^N-1\), so brute force is impossible. The key observation is that divisibility by \(250\) depends only on residue classes modulo \(250\), not on the full size of the numbers \(i^i\).
Mathematical Approach
Let
$$r_i=a_i\bmod 250=i^i\bmod 250.$$
Then for any subset \(S\),
$$\sum_{i\in S} a_i \equiv \sum_{i\in S} r_i \pmod{250}.$$
So the original problem is equivalent to counting subsets whose residue sum is \(0\) modulo \(250\).
Why Reduction Modulo \(250\) Is Sufficient
The congruence rule
$$x\equiv y\pmod{250}\quad\Longrightarrow\quad x+z\equiv y+z\pmod{250}$$
shows that divisibility of a sum by \(250\) depends only on each summand's class in \(\mathbb{Z}/250\mathbb{Z}\). Therefore the gigantic integers \(i^i\) never need to be stored explicitly. Only the 250 possible residues matter.
Subset-Sum DP on the Cyclic Group \(\mathbb{Z}/250\mathbb{Z}\)
For \(k=0,1,\dots,N\), define
$$dp_k(t)=\#\left\{S\subseteq\{1,\dots,k\}:\sum_{i\in S} r_i\equiv t\pmod{250}\right\}.$$
The desired count is \(dp_N(0)-1\), because \(dp_N(0)\) includes the empty subset.
Initial Condition
Before processing any terms, there is exactly one subset of \(\{1,\dots,0\}\): the empty subset. Its sum is \(0\). Hence
$$dp_0(0)=1,\qquad dp_0(t)=0\quad(1\le t\le 249).$$
Transition Formula
When we process residue \(r_k\), every old subset has two possibilities:
1. Exclude \(k\): its residue class stays the same.
2. Include \(k\): its residue class shifts by \(r_k\) modulo \(250\).
Therefore
$$dp_k(t)=dp_{k-1}(t)+dp_{k-1}(t-r_k)\pmod{M},$$
where \(t-r_k\) is interpreted modulo \(250\).
The code implements the same recurrence in forward form with a temporary array next:
$$next[t]=dp[t],$$
$$next[(t+r_k)\bmod 250]\leftarrow next[(t+r_k)\bmod 250]+dp[t]\pmod{M}.$$
Using a second array is important: it guarantees 0/1 behavior. If we updated dp in place, a newly created subset could be reused in the same iteration, which would incorrectly allow the same element to be chosen multiple times.
Generating-Function View
The same recurrence can be written as a product of polynomials modulo \(x^{250}-1\):
$$F_N(x)=\prod_{i=1}^{N}\left(1+x^{r_i}\right)\pmod{x^{250}-1}.$$
The coefficient of \(x^t\) in \(F_N(x)\) counts subsets whose residue sum is \(t\) modulo \(250\). The dynamic program is simply a coefficient-update algorithm for this product.
Computing \(i^i\bmod 250\) Efficiently
The code uses repeated squaring to compute
$$r_i=i^i\bmod 250$$
in \(O(\log i)\) time. This is the standard modular exponentiation recurrence:
$$b^{2m}\equiv (b^2)^m\pmod{250},\qquad b^{2m+1}\equiv b\cdot (b^2)^m\pmod{250}.$$
Because multiplication is reduced modulo \(250\) at every step, intermediate numbers stay small.
Worked Example: First 10 Terms
For \(N=10\), the residues are
$$1^1,2^2,\dots,10^{10}\equiv 1,4,27,6,125,156,43,216,239,0 \pmod{250}.$$
The checkpoint in the code states that the answer is \(5\). Indeed, the non-empty divisible subsets are:
$$\{1,3,4,8\},\qquad \{1,2,4,9\},\qquad \{10\},$$
$$\{1,3,4,8,10\},\qquad \{1,2,4,9,10\}.$$
For example,
$$1^1+3^3+4^4+8^8\equiv 1+27+6+216=250\equiv 0\pmod{250},$$
and since \(10^{10}\equiv 0\pmod{250}\), appending the 10th term preserves divisibility. Hence there are exactly \(5\) valid non-empty subsets.
Why the Final Subtraction Is Necessary
The DP starts from the empty subset, so \(dp_N(0)\) counts all subsets with residue \(0\), including
$$S=\varnothing.$$
Since the problem asks only for non-empty subsets, the final answer is
$$\boxed{(dp_N(0)-1)\bmod M.}$$
Complexity Analysis
There are \(N\) iterations, and each iteration updates all \(250\) residue classes. Hence the dynamic-programming work is
$$O(N\cdot 250)=O(ND).$$
The memory usage is \(O(250)\), since only the current and next DP rows are stored. Modular exponentiation adds \(O(\log i)\) work per term, so the full cost is \(O(ND+N\log N)\); for fixed \(D=250\), this is still easily practical.
How the Code Works
The C++ solution initializes dp[0]=1 and all other states to zero. For each \(i\) from \(1\) to limit, it computes residue = powmod_int(i, i, divisor), copies dp into next, applies the include-transition to every residue class, and then swaps the arrays. After the loop, dp[0] contains the number of divisible subsets including the empty one, so the code returns (dp[0] + modulo - 1) % modulo. The Python and Java versions implement the same recurrence.
Footnotes and References
- Problem page: https://projecteuler.net/problem=250
- Dynamic programming: Wikipedia — Dynamic programming
- Modular exponentiation: Wikipedia — Modular exponentiation
- Cyclic groups and modular arithmetic: Wikipedia — Modular arithmetic
- Generating functions in combinatorics: Wikipedia — Generating function
Mathematical approach · C++ solution · Python solution · Java solution
Previous: Problem 249 · All Project Euler solutions · Next: Problem 251