Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

Complete solutions in C++, Python & Java — with step-by-step mathematical explanations

All Problems

Problem 827: Pythagorean Triple Occurrence

View on Project Euler

Project Euler Problem 827 Solution

EulerSolve provides an optimized solution for Project Euler Problem 827, Pythagorean Triple Occurrence, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary For a positive integer \(N\), let \(T(N)\) be the number of distinct positive integer Pythagorean triples \((a,b,c)\) with \(a^2+b^2=c^2\) in which \(N\) appears as one of the three side lengths, counting \((a,b,c)\) and \((b,a,c)\) as the same triple. The task is to find, for each target count \(10^k\) with \(1\le k\le 18\), the smallest \(N\) satisfying \(T(N)=10^k\), and then sum those minima modulo \(409120391\). A direct search over triples or over candidate integers is infeasible. The solution instead derives a closed multiplicative formula for \(T(N)\), then inverts that formula by a constrained minimization over prime exponents. Mathematical Approach Write the prime factorization of \(N\) as $N=2^{e_2}\prod_{p\equiv 1 \pmod{4}} p^{\alpha_p}\prod_{q\equiv 3 \pmod{4}} q^{\beta_q}.$ Define the two odd products $A=\prod_{p\equiv 1 \pmod{4}} (2\alpha_p+1),\qquad R=\prod_{q\equiv 3 \pmod{4}} (2\beta_q+1).$ It is also convenient to encode the power of \(2\) by $u=\begin{cases} 1,& e_2=0,\\ 2e_2-1,& e_2\ge 1. \end{cases}$ Step 1: Count triples with hypotenuse \(N\) Distinct right triangles with hypotenuse \(N\) correspond to positive representations of \(N^2\) as a sum of two squares. A standard consequence of the sum-of-two-squares theorem is $r_2(N^2)=4A,$ where \(r_2(m)\) counts ordered integer pairs \((x,y)\) satisfying \(x^2+y^2=m\)....

Detailed mathematical approach

Problem Summary

For a positive integer \(N\), let \(T(N)\) be the number of distinct positive integer Pythagorean triples \((a,b,c)\) with \(a^2+b^2=c^2\) in which \(N\) appears as one of the three side lengths, counting \((a,b,c)\) and \((b,a,c)\) as the same triple. The task is to find, for each target count \(10^k\) with \(1\le k\le 18\), the smallest \(N\) satisfying \(T(N)=10^k\), and then sum those minima modulo \(409120391\).

A direct search over triples or over candidate integers is infeasible. The solution instead derives a closed multiplicative formula for \(T(N)\), then inverts that formula by a constrained minimization over prime exponents.

Mathematical Approach

Write the prime factorization of \(N\) as

$N=2^{e_2}\prod_{p\equiv 1 \pmod{4}} p^{\alpha_p}\prod_{q\equiv 3 \pmod{4}} q^{\beta_q}.$

Define the two odd products

$A=\prod_{p\equiv 1 \pmod{4}} (2\alpha_p+1),\qquad R=\prod_{q\equiv 3 \pmod{4}} (2\beta_q+1).$

It is also convenient to encode the power of \(2\) by

$u=\begin{cases} 1,& e_2=0,\\ 2e_2-1,& e_2\ge 1. \end{cases}$

Step 1: Count triples with hypotenuse \(N\)

Distinct right triangles with hypotenuse \(N\) correspond to positive representations of \(N^2\) as a sum of two squares. A standard consequence of the sum-of-two-squares theorem is

$r_2(N^2)=4A,$

where \(r_2(m)\) counts ordered integer pairs \((x,y)\) satisfying \(x^2+y^2=m\).

Among these representations, four are degenerate: \((\pm N,0)\) and \((0,\pm N)\). Every genuine triangle is counted eight times because of sign choices and swapping the two legs. Therefore the number of distinct triangles having hypotenuse \(N\) is

$H(N)=\frac{r_2(N^2)-4}{8}=\frac{A-1}{2}.$

Only primes congruent to \(1 \pmod{4}\) affect this count. Primes congruent to \(3 \pmod{4}\) and the factor \(2\) only appear as square contributions in \(N^2\), so they do not create additional representations.

Step 2: Count triples with leg \(N\)

If \(N\) is odd, every factorization \(N^2=st\) with \(s<t\) gives one triangle

$\left(N,\frac{t-s}{2},\frac{t+s}{2}\right),$

so the number of such triangles is the number of unordered divisor pairs of \(N^2\):

$L(N)=\frac{d(N^2)-1}{2}\qquad (e_2=0).$

If \(N\) is even, write \(N=2m\). Then every factorization \(m^2=st\) with \(s<t\) gives

$\left(N,t-s,t+s\right),$

hence

$L(N)=\frac{d(m^2)-1}{2}=\frac{d\!\left((N/2)^2\right)-1}{2}\qquad (e_2\ge 1).$

Using the factorization of \(N\), both cases collapse to one formula:

$L(N)=\frac{uAR-1}{2}.$

Step 3: Combine the two occurrence counts

A number cannot be both a leg and the hypotenuse in the same right triangle, so the total occurrence count is simply

$T(N)=H(N)+L(N)=\frac{A(uR+1)}{2}-1.$

This is the key identity used by the solver. If we want exactly \(n\) occurrences, then after setting

$s=n+1,$

we must satisfy

$s=\frac{A(uR+1)}{2}.$

Since \(A\) is odd, every solution begins by choosing an odd divisor \(a\mid s\), forcing

$uR=\frac{2s}{a}-1.$

The right-hand side is again odd, so we split it once more as

$u\cdot r=\frac{2s}{a}-1,$

where \(u\) is either \(1\) or of the form \(2e_2-1\), and \(r\) must equal \(\prod_{q\equiv 3 \pmod{4}} (2\beta_q+1)\).

Step 4: Turn odd factors into prime exponents

The quantity \(A\) must be represented as a product of odd factors

$A=\prod_i f_i,\qquad f_i=2\alpha_i+1,$

and similarly

$R=\prod_j g_j,\qquad g_j=2\beta_j+1.$

Once an odd factor is chosen, the exponent is fixed: \(\alpha=(f-1)/2\) or \(\beta=(g-1)/2\). So the inverse problem becomes: partition the required odd product into factors of the form \(2e+1\), then place those exponents on allowed primes.

To minimize \(N\), larger exponents must be assigned to smaller primes. Indeed, if \(p<q\) and \(x>y\), then

$p^x q^y < p^y q^x.$

Therefore the optimal partition in each residue class is searched in nonincreasing odd factors and assigned to the increasing primes of that class.

Step 5: Compare candidates by logarithms

The actual minima can be enormous, so the implementations compare candidates using high-precision base-2 logarithms:

$\log_2 N=e_2+\sum_i \alpha_i\log_2 p_i+\sum_j \beta_j\log_2 q_j.$

Because the logarithm is strictly increasing, the candidate with smaller logarithmic value is exactly the smaller integer. Once the best exponent pattern is known, the final value is reconstructed modulo \(409120391\) by modular exponentiation.

Worked Example: \(N=15\)

We have \(15=3^1\cdot 5^1\), so

$A=3,\qquad R=3,\qquad u=1.$

The hypotenuse contribution is

$H(15)=\frac{3-1}{2}=1,$

coming from \((9,12,15)\).

The leg contribution is

$L(15)=\frac{1\cdot 3\cdot 3-1}{2}=4,$

coming from \((8,15,17)\), \((15,20,25)\), \((15,36,39)\), and \((15,112,113)\).

Therefore

$T(15)=1+4=5.$

So 15 is a valid witness for target count \(5\), and the implementations verify that it is the smallest such integer.

How the Code Works

The C++, Python, and Java implementations first generate enough small primes in the residue classes \(1 \pmod{4}\) and \(3 \pmod{4}\). They also use fast 64-bit primality testing and factorization so that every odd divisor needed by the search can be generated and cached efficiently.

For a fixed odd product in one residue class, the implementation runs a memoized depth-first search over its odd divisors. Choosing one divisor corresponds to choosing one factor \(2e+1\), hence one prime exponent. The recursion enforces nonincreasing chosen factors, which avoids duplicate partitions and automatically places larger exponents on smaller primes.

For a target count \(n\), the implementation sets \(s=n+1\), enumerates odd divisors \(a\mid s\), computes the forced odd remainder \(2s/a-1\), and then tries every odd divisor of that remainder as the possible \(u\) attached to the power of \(2\). The remaining factor is solved in the \(3 \pmod{4}\) prime class, while \(a\) itself is solved in the \(1 \pmod{4}\) prime class. The best combined logarithmic score gives the smallest integer with exactly \(n\) occurrences.

Finally, the implementation evaluates this inverse solver for \(n=10,10^2,\dots,10^{18}\), reconstructs each minimum modulo \(409120391\), and sums those values modulo the same modulus.

Complexity Analysis

The dominant cost comes from factoring the odd integers derived from \(n+1\) and enumerating their odd divisors. If \(\tau(m)\) denotes the divisor function, then each recursive optimization depends on the divisor structure of the relevant odd product rather than on the size of the final minimum itself. Memoization collapses repeated subproblems determined by the remaining product, the next prime slot, and the previously chosen odd factor.

For the concrete targets \(10^1,\dots,10^{18}\), the search trees stay manageable because every recursive step removes at least one odd factor \(2e+1\). In practice, runtime is dominated by Pollard-rho factorization plus divisor generation, while memory is dominated by cached divisor lists and memoized optimal subproblems.

Footnotes and References

  1. Problem page: Project Euler 827
  2. Pythagorean triples: Wikipedia — Pythagorean triple
  3. Sum of two squares theorem: Wikipedia — Fermat's theorem on sums of two squares
  4. Divisor function: Wikipedia — Divisor function
  5. Pollard's rho algorithm: Wikipedia — Pollard's rho algorithm

Mathematical approach · C++ solution · Python solution · Java solution

Previous: Problem 826 · All Project Euler solutions · Next: Problem 828

Need help with a problem? Ask me! 💡
e
✦ Euler GLM 5.2
Hi! I'm Euler. Ask me anything about Project Euler problems, math concepts, or solution approaches! 🧮