Problem 753: Fermat Equation
View on Project EulerProject Euler Problem 753 Solution
EulerSolve provides an optimized solution for Project Euler Problem 753, Fermat Equation, with C++, Python, Java, and a step-by-step mathematical explanation.
Problem Summary For a prime \(p\), define $F(p)=\#\left\{(a,b,c)\in\{1,\dots,p-1\}^3 : a^3+b^3\equiv c^3 \pmod p\right\}.$ So \(F(p)\) counts ordered triples of nonzero residues modulo \(p\) that satisfy the Fermat-type congruence \(a^3+b^3=c^3\). The goal is to compute $\sum_{\substack{p\lt 6\cdot 10^6 \\ p\text{ prime}}} F(p).$ A direct \(O(p^3)\) count for every prime would be far too slow, so the solution uses the structure of the cube map on \(\mathbb F_p^\times\) and a closed formula for the difficult congruence class \(p\equiv 1\pmod 3\). Mathematical Approach The key observation is that the number of cube roots of a nonzero residue depends entirely on the residue class of \(p\) modulo \(3\). That turns the whole problem into a clean case split. Step 1: Rewrite the Counting Problem in \(\mathbb F_p^\times\) Because \(a,b,c\) are chosen from \(\{1,\dots,p-1\}\), all three variables live in the multiplicative group \(\mathbb F_p^\times\), which has size \(p-1\). For a nonzero residue \(s\), let \(N_p(s)\) be the number of nonzero solutions of \(x^3=s\). Then $F(p)=\sum_{a\in\mathbb F_p^\times}\sum_{b\in\mathbb F_p^\times} N_p(a^3+b^3).$ So the job is to understand how many cube roots a residue has and how often \(a^3+b^3\) lands in each class. Step 2: Handle the Easy Branch \(p\equiv 2\pmod 3\) The group \(\mathbb F_p^\times\) is cyclic of size \(p-1\)....
Detailed mathematical approach
Problem Summary
For a prime \(p\), define
$F(p)=\#\left\{(a,b,c)\in\{1,\dots,p-1\}^3 : a^3+b^3\equiv c^3 \pmod p\right\}.$
So \(F(p)\) counts ordered triples of nonzero residues modulo \(p\) that satisfy the Fermat-type congruence \(a^3+b^3=c^3\). The goal is to compute
$\sum_{\substack{p\lt 6\cdot 10^6 \\ p\text{ prime}}} F(p).$
A direct \(O(p^3)\) count for every prime would be far too slow, so the solution uses the structure of the cube map on \(\mathbb F_p^\times\) and a closed formula for the difficult congruence class \(p\equiv 1\pmod 3\).
Mathematical Approach
The key observation is that the number of cube roots of a nonzero residue depends entirely on the residue class of \(p\) modulo \(3\). That turns the whole problem into a clean case split.
Step 1: Rewrite the Counting Problem in \(\mathbb F_p^\times\)
Because \(a,b,c\) are chosen from \(\{1,\dots,p-1\}\), all three variables live in the multiplicative group \(\mathbb F_p^\times\), which has size \(p-1\).
For a nonzero residue \(s\), let \(N_p(s)\) be the number of nonzero solutions of \(x^3=s\). Then
$F(p)=\sum_{a\in\mathbb F_p^\times}\sum_{b\in\mathbb F_p^\times} N_p(a^3+b^3).$
So the job is to understand how many cube roots a residue has and how often \(a^3+b^3\) lands in each class.
Step 2: Handle the Easy Branch \(p\equiv 2\pmod 3\)
The group \(\mathbb F_p^\times\) is cyclic of size \(p-1\). If \(p\equiv 2\pmod 3\), then \(\gcd(3,p-1)=1\), so the map
$x\longmapsto x^3$
is a permutation of \(\mathbb F_p^\times\). Therefore every nonzero residue has exactly one nonzero cube root.
There are \((p-1)^2\) ordered pairs \((a,b)\). Among them, exactly \(p-1\) satisfy \(a^3+b^3\equiv 0\pmod p\), because for each nonzero \(a\) there is exactly one choice of \(b\), namely \(b\equiv -a\), that cancels the sum.
Those pairs contribute nothing, since \(c\) is required to be nonzero. Every other pair contributes exactly one value of \(c\). Hence
$F(p)=(p-1)^2-(p-1)=(p-1)(p-2)\qquad (p\equiv 2\pmod 3).$
The small primes fit naturally into this picture: \(F(2)=0\), while \(F(3)=2\) can be checked directly.
Step 3: Understand the Hard Branch \(p\equiv 1\pmod 3\)
If \(p\equiv 1\pmod 3\), then \(3\mid (p-1)\). The cube map is no longer bijective: its kernel has size \(3\), so every nonzero cubic residue has exactly three cube roots, and non-cubic residues have none.
What remains is to measure how often \(a^3+b^3\) lands in the cubic-residue set. That is the nontrivial part of the problem, and the implementations use the classical closed form
$F(p)=(p-1)(p-8+t)\qquad (p\equiv 1\pmod 3),$
where the integer \(t\) comes from a quadratic representation of \(p\). This formula is the cubic-character/Jacobi-sum evaluation encoded by the program.
Step 4: Determine \(t\) from the Representation \(4p=27u^2+t^2\)
For every prime \(p\equiv 1\pmod 3\), there exist integers \(u\) and \(t\) such that
$4p=27u^2+t^2,\qquad t\equiv 1\pmod 3.$
Up to signs, this representation is unique. The sign of \(t\) matters in the formula, so once \(|t|\) is found the correct sign is chosen by the congruence condition \(t\equiv 1\pmod 3\).
Substituting that value into the closed form immediately gives \(F(p)\).
Step 5: Assemble the Prime Sum
The complete evaluation is therefore
$F(p)= \begin{cases} 0,&p=2,\\ 2,&p=3,\\ (p-1)(p-2),&p\equiv 2\pmod 3,\\ (p-1)(p-8+t),&p\equiv 1\pmod 3,\ 4p=27u^2+t^2,\ t\equiv 1\pmod 3. \end{cases}$
After applying this formula prime by prime, the required answer is obtained by summing over all primes below \(6\cdot 10^6\).
Worked Example
Two small primes show both branches.
For \(p=5\), we are in the easy branch \(p\equiv 2\pmod 3\), so
$F(5)=(5-1)(5-2)=4\cdot 3=12.$
For \(p=19\), we are in the hard branch \(p\equiv 1\pmod 3\). We have
$4p=76=27\cdot 1^2+7^2,$
and \(7\equiv 1\pmod 3\), so \(t=7\). Therefore
$F(19)=(19-1)(19-8+7)=18\cdot 18=324.$
These values agree with the formula used by the implementations.
How the Code Works
The C++, Python, and Java implementations all follow the same plan. First they build a prime sieve up to \(6\cdot 10^6\), so each prime can be processed exactly once.
Next they precompute the monotone list
$27\cdot 1^2,\ 27\cdot 2^2,\ 27\cdot 3^2,\ \dots$
up to \(4\cdot 6\cdot 10^6\). This turns the search for the representation \(4p=27u^2+t^2\) into a scan over candidate values of \(27u^2\).
For each prime \(p\):
If \(p=3\), the contribution is \(2\).
If \(p\equiv 2\pmod 3\), the implementation adds \((p-1)(p-2)\).
If \(p\equiv 1\pmod 3\), it loops through the precomputed \(27u^2\) values not exceeding \(4p\), computes
$4p-27u^2,$
tests whether that remainder is a perfect square, and when a square is found uses its root as \(|t|\). The sign is then fixed so that \(t\equiv 1\pmod 3\), and the closed formula \((p-1)(p-8+t)\) is added to the total.
All three implementations accumulate the final sum in 64-bit arithmetic. One implementation also checks the formula against direct enumeration for small primes before printing the final total.
Complexity Analysis
Let \(L=6\cdot 10^6\). The prime sieve costs \(O(L\log\log L)\) time and \(O(L)\) memory. Precomputing the values \(27u^2\) takes \(O(\sqrt L)\) time and memory.
For primes with \(p\equiv 1\pmod 3\), the representation search scans \(u\) while \(27u^2\le 4p\), so a conservative upper bound is \(O(\sqrt p)\) work per such prime. Summed over all primes, this gives the practical estimate
$O\!\left(L\log\log L+\pi(L)\sqrt L\right)$
with \(O(L)\) total memory. In practice it is faster than this bound suggests, because the search stops as soon as the first valid representation is found.
Footnotes and References
- Problem page: Project Euler 753
- Finite fields: Wikipedia — Finite field
- Cubic residues: Wikipedia — Cubic residue
- Jacobi sums: Wikipedia — Jacobi sum
- Binary quadratic forms: Wikipedia — Binary quadratic form