Inscribed Circles of Triangles with One Angle of 60 Degrees
Let T(n) be the number of integer-sided triangles with exactly one 60^circ angle whose incircle radius is at most n. Given that T(100)=1234, T(1000)=22767, and T(10000)=359912, find T(1053779).
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Let’s call an integer sided triangle with exactly one angle of \(60\) degrees a \(60\)-degree triangle.
Let \(r\) be the radius of the inscribed circle of such a \(60\)-degree triangle.
There are \(1234\) \(60\)-degree triangles for which \(r \le 100\).
Let \(T(n)\) be the number of \(60\)-degree triangles for which \(r \le n\), so
\(T(100) = 1234\), \(T(1000) = 22767\), and \(T(10000) = 359912\).
Find \(T(1053779)\).
Problem 195: Inscribed Circles of Triangles with One Angle of 60 Degrees
Mathematical Development
Theorem 1. (Incircle Radius for a 60-Degree Triangle.) Consider a triangle with sides , and included angle . The opposite side is , the area is , and the incircle radius is
Proof. By the law of cosines, . The area is . The incircle radius satisfies where is the semi-perimeter, giving .
Theorem 2. (Integer Side Condition via Eisenstein Integers.) For to be a positive integer, the norm form must be a perfect square. This norm is the norm of the Eisenstein integer where . The ring is a unique factorization domain.
Proof. The Eisenstein integers have norm (equivalently under a sign change of ). This ring is a Euclidean domain (with the norm as Euclidean function), hence a UFD. The factorization of in determines when it is a perfect square.
Theorem 3. (Primitive 60-Degree Triple Parameterization.) All primitive integer triples with , , , fall into two families parameterized by coprime integers :
Family 1 ():
Family 2 ():
In both families, one must also check positivity ( requires ) and primitivity ().
Proof. Factor in . For this to equal , the ideal factorization must pair up. Using the UFD property, write for some unit and Eisenstein integer . Expanding (using , so , giving ). Matching real and -components and accounting for the units yields the two families. The condition causes all three of (before division) to be divisible by 3, producing Family 2 after dividing by 3.
Lemma 1. (Scaling.) For each primitive triple with primitive incircle radius , the scaled triple has incircle radius . The number of valid scaled copies with is .
Proof. .
Lemma 2. (Multiplicity.) Each unordered pair with gives one triangle (the 60-degree angle is between sides and ). If , the triangle is equilateral with all angles equal to 60 degrees, counted once. Additionally, and represent the same triangle, so each primitive triple with contributes twice in the parameterization (once as and once as ).
Proof. The 60-degree angle is uniquely determined by the law of cosines given . The triangle is unchanged by swapping and .
Editorial
The heavy algebra is already done in the parameterization step, so the algorithm only has to enumerate coprime parameter pairs. For coprime integers p > q > 0, the primitive triangle falls into one of two cases depending on whether p-q is divisible by 3. The key simplification is that the primitive inradius collapses to
so once a primitive triple is known, the number of scaled copies with radius at most R is just a floor division in terms of pq.
That turns the search into a lattice-point count over coprime pairs. For each q, there is a simple upper bound on p coming from the larger of the two radius formulas, so the double loop stays manageable. Each admissible pair contributes either floor((2R/\sqrt3)/(pq)) or floor((6R/\sqrt3)/(pq)), and the sum of those contributions is exactly T(R).
Pseudocode
Set R = 1053779.
Precompute the two radius limits 2R / sqrt(3) and 6R / sqrt(3).
For each q from 1 up to the point where pq can no longer fit the larger limit:
let p run from q + 1 up to floor((6R / sqrt(3)) / q);
skip the pair if gcd(p, q) is not 1.
If p - q is divisible by 3:
add floor((6R / sqrt(3)) / (p q)) to the answer.
Otherwise:
add floor((2R / sqrt(3)) / (p q)) to the answer.
Return the final count.
Complexity Analysis
- Time: arithmetic operations. The outer loop over
qruns to , and for eachqthe inner loop runs to , giving the harmonic-series total. - Space: beyond the loop variables.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <cassert>
#include <cmath>
#include <iostream>
#include <numeric>
using namespace std;
long long gcd_ll(long long a, long long b) {
while (b != 0) {
long long t = a % b;
a = b;
b = t;
}
return a;
}
long long count_triangles(long long limit) {
const long double sqrt3 = sqrt(static_cast<long double>(3.0));
const long double limit_plain = 2.0L * limit / sqrt3;
const long double limit_div3 = 6.0L * limit / sqrt3;
const long long q_max = static_cast<long long>(sqrt(limit_div3)) + 2;
long long total = 0;
for (long long q = 1; q <= q_max; ++q) {
long long p_max = static_cast<long long>(limit_div3 / q);
for (long long p = q + 1; p <= p_max; ++p) {
if (gcd_ll(p, q) != 1) {
continue;
}
long long product = p * q;
if ((p - q) % 3 == 0) {
total += static_cast<long long>(limit_div3 / product);
} else {
total += static_cast<long long>(limit_plain / product);
}
}
}
return total;
}
int main() {
assert(count_triangles(100) == 1234);
assert(count_triangles(1000) == 22767);
assert(count_triangles(10000) == 359912);
long long answer = count_triangles(1053779);
assert(answer == 75085391LL);
cout << answer << '\n';
return 0;
}
"""
Project Euler Problem 195: Inscribed Circles of Triangles with One Angle of 60 Degrees
Count 60-degree triangles with incircle radius at most 1,053,779.
"""
import math
SQRT3 = math.sqrt(3.0)
def count_triangles(limit):
limit_plain = 2.0 * limit / SQRT3
limit_div3 = 6.0 * limit / SQRT3
q_max = int(math.sqrt(limit_div3)) + 2
total = 0
for q in range(1, q_max + 1):
p_max = int(limit_div3 / q)
for p in range(q + 1, p_max + 1):
if math.gcd(p, q) != 1:
continue
product = p * q
if (p - q) % 3 == 0:
total += int(limit_div3 / product)
else:
total += int(limit_plain / product)
return total
def solve():
return count_triangles(1053779)
if __name__ == "__main__":
assert count_triangles(100) == 1234
assert count_triangles(1000) == 22767
assert count_triangles(10000) == 359912
answer = solve()
assert answer == 75085391
print(answer)