Project Euler Problem 279
How many triangles are there with integral sides, at least one integral angle (measured in degrees), and a perimeter tha
Solution
Answer: 416577688
Let the triangle have integer sides $a,b,c$, and suppose one angle is an integer number of degrees.
By the Law of Cosines,
$$\cos \theta = \frac{a^2+b^2-c^2}{2ab},$$
so $\cos\theta$ is rational.
A classical theorem of Niven says:
If $\theta/\pi$ is rational and $\cos\theta$ is rational, then
$$\cos\theta \in \left{0,\pm \frac12,\pm1\right}.$$
For a nondegenerate triangle, this leaves only:
- $60^\circ$,
- $90^\circ$,
- $120^\circ$.
So the problem reduces to counting all integer triangles of these three types with perimeter $\le 10^8$.
1. Right triangles ($90^\circ$)
Primitive Pythagorean triples are parameterized by
$$a=m^2-n^2,\qquad b=2mn,\qquad c=m^2+n^2,$$
with
$$m>n,\quad \gcd(m,n)=1,\quad m-n\text{ odd}.$$
Their perimeter is
$$p=2m(m+n).$$
Every nonprimitive triple is a multiple of a primitive one, so the number contributed is
$$\sum \left\lfloor \frac{N}{2m(m+n)} \right\rfloor .$$
2. $120^\circ$ triangles
Suppose the $120^\circ$ angle is opposite side $c$. Then
$$c^2=a^2+b^2+ab.$$
Primitive solutions are parameterized by
$$a=m^2-n^2,$$
$$b=2mn+n^2,$$
$$c=m^2+mn+n^2,$$
with
$$m>n,\qquad \gcd(m,n)=1,\qquad m\not\equiv n\pmod 3.$$
The perimeter is
$$p=2m^2+3mn+n^2.$$
Hence the contribution is
$$\sum \left\lfloor \frac{N}{2m^2+3mn+n^2} \right\rfloor .$$
3. $60^\circ$ triangles
Besides equilateral triangles, every primitive $60^\circ$ triangle arises from a primitive $120^\circ$ triangle.
Starting from a primitive $120^\circ$ triangle $(a,b,c)$,
$$(a,c,a+b) \quad\text{and}\quad (b,c,a+b)$$
are primitive $60^\circ$ triangles.
Their primitive perimeters become
$$p_1 = 3m(m+n),$$
$$p_2 = (2m+n)(m+2n).$$
In addition, equilateral triangles contribute
$$\left\lfloor \frac{N}{3}\right\rfloor .$$
So the total number of $60^\circ$ triangles is
$$\left\lfloor \frac{N}{3}\right\rfloor + \sum \left\lfloor \frac{N}{3m(m+n)} \right\rfloor + \sum \left\lfloor \frac{N}{(2m+n)(m+2n)} \right\rfloor .$$
Python implementation
from math import gcd, isqrt
N = 10**8
# ------------------------------------------------------------
# Count 90-degree triangles
# ------------------------------------------------------------
def count_90(limit):
total = 0
for m in range(2, isqrt(limit // 2) + 2):
for n in range(1, m):
# Primitive Pythagorean conditions
if gcd(m, n) != 1:
continue
if (m - n) % 2 == 0:
continue
perimeter = 2 * m * (m + n)
if perimeter > limit:
break
total += limit // perimeter
return total
# ------------------------------------------------------------
# Count 120-degree triangles
# ------------------------------------------------------------
def count_120(limit):
total = 0
for m in range(2, isqrt(limit) + 2):
for n in range(1, m):
# Primitive conditions
if gcd(m, n) != 1:
continue
if (m - n) % 3 == 0:
continue
perimeter = 2 * m * m + 3 * m * n + n * n
if perimeter > limit:
break
total += limit // perimeter
return total
# ------------------------------------------------------------
# Count 60-degree triangles
# ------------------------------------------------------------
def count_60(limit):
# Equilateral triangles
total = limit // 3
for m in range(2, isqrt(limit) + 2):
for n in range(1, m):
if gcd(m, n) != 1:
continue
if (m - n) % 3 == 0:
continue
p1 = 3 * m * (m + n)
p2 = (2 * m + n) * (m + 2 * n)
if p1 <= limit:
total += limit // p1
if p2 <= limit:
total += limit // p2
return total
c90 = count_90(N)
c120 = count_120(N)
c60 = count_60(N)
answer = c90 + c120 + c60
print(answer)
Code walkthrough
count_90
Implements Euclid’s formula for primitive Pythagorean triples.
gcd(m,n)==1ensures primitiveness.(m-n)%2==1ensures opposite parity.- Every multiple is counted using:
$$\left\lfloor \frac{N}{p} \right\rfloor .$$
count_120
Uses the primitive parameterization for $120^\circ$ triangles.
The condition
$$m\not\equiv n \pmod 3$$
removes nonprimitive duplicates.
count_60
Counts:
- equilateral triangles,
- the two $60^\circ$ families generated from each primitive $120^\circ$ triangle.
Small verification
For $N=100$, the program gives:
- $17$ right triangles,
- $14$ $120^\circ$ triangles,
- $53$ $60^\circ$ triangles,
for a total of
$$17+14+53=84.$$
Direct brute force confirms this exactly.
Final verification
The final count is on the order of several hundred million, which is reasonable because:
- primitive families are two-parameter lattices,
- each primitive triangle contributes many multiples,
- the perimeter bound is very large ($10^8$).
The computation is fast and uses only $O(\sqrt N)$-scale loops.
Answer: 416577688