All Euler problems
Project Euler

Inscribed Circles of Triangles with One Angle of 60 Degrees

How many triangles with integer sides having one angle of exactly 60 degrees have an inscribed circle (incircle) with radius not exceeding 10^5?

Source sync Apr 19, 2026
Problem #0195
Level Level 12
Solved By 1,714
Languages C++, Python
Answer 75085391
Length 440 words
geometrynumber_theorymodular_arithmetic

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 Foundation

Theorem 1. (Incircle Radius for a 60-Degree Triangle.) Consider a triangle with sides aa, bb and included angle C=60°C = 60°. The opposite side is c=a2+b2abc = \sqrt{a^2 + b^2 - ab}, the area is Δ=34ab\Delta = \frac{\sqrt{3}}{4}ab, and the incircle radius is

r=3ab2(a+b+c).r = \frac{\sqrt{3}\,ab}{2(a + b + c)}.

Proof. By the law of cosines, c2=a2+b22abcos(60°)=a2+b2abc^2 = a^2 + b^2 - 2ab\cos(60°) = a^2 + b^2 - ab. The area is Δ=12absin(60°)=34ab\Delta = \frac{1}{2}ab\sin(60°) = \frac{\sqrt{3}}{4}ab. The incircle radius satisfies r=Δ/sr = \Delta / s where s=(a+b+c)/2s = (a + b + c)/2 is the semi-perimeter, giving r=3ab2(a+b+c)r = \frac{\sqrt{3}\,ab}{2(a + b + c)}. \square

Theorem 2. (Integer Side Condition via Eisenstein Integers.) For c=a2ab+b2c = \sqrt{a^2 - ab + b^2} to be a positive integer, the norm form a2ab+b2a^2 - ab + b^2 must be a perfect square. This norm is the norm of the Eisenstein integer a+bωa + b\omega where ω=e2πi/3\omega = e^{2\pi i/3}. The ring Z[ω]\mathbb{Z}[\omega] is a unique factorization domain.

Proof. The Eisenstein integers Z[ω]\mathbb{Z}[\omega] have norm N(x+yω)=x2xy+y2N(x + y\omega) = x^2 - xy + y^2 (equivalently x2+xy+y2x^2 + xy + y^2 under a sign change of yy). This ring is a Euclidean domain (with the norm as Euclidean function), hence a UFD. The factorization of a2ab+b2a^2 - ab + b^2 in Z[ω]\mathbb{Z}[\omega] determines when it is a perfect square. \square

Theorem 3. (Primitive 60-Degree Triple Parameterization.) All primitive integer triples (a,b,c)(a, b, c) with c2=a2ab+b2c^2 = a^2 - ab + b^2, gcd(a,b)=1\gcd(a, b) = 1, a,b,c>0a, b, c > 0, fall into two families parameterized by coprime integers m>n>0m > n > 0:

Family 1 (m≢n(mod3)m \not\equiv n \pmod{3}):

a=2mn+n2,b=m2n2,c=m2mn+n2.a = 2mn + n^2, \quad b = m^2 - n^2, \quad c = m^2 - mn + n^2.

Family 2 (mn(mod3)m \equiv n \pmod{3}):

a=2mn+n23,b=m2n23,c=m2mn+n23.a = \frac{2mn + n^2}{3}, \quad b = \frac{m^2 - n^2}{3}, \quad c = \frac{m^2 - mn + n^2}{3}.

In both families, one must also check positivity (b>0b > 0 requires m>nm > n) and primitivity (gcd(a,b)=1\gcd(a, b) = 1).

Proof. Factor a2ab+b2=(abω)(abωˉ)a^2 - ab + b^2 = (a - b\omega)(a - b\bar{\omega}) in Z[ω]\mathbb{Z}[\omega]. For this to equal c2c^2, the ideal factorization must pair up. Using the UFD property, write abω=ϵα2a - b\omega = \epsilon \cdot \alpha^2 for some unit ϵ\epsilon and Eisenstein integer α=m+nω\alpha = m + n\omega. Expanding α2=(m+nω)2=m2+2mnω+n2ω2=(m2n2)+(2mnn2)ω\alpha^2 = (m + n\omega)^2 = m^2 + 2mn\omega + n^2\omega^2 = (m^2 - n^2) + (2mn - n^2)\omega (using ω2=1ω\omega^2 = -1 - \omega, so n2ω2=n2n2ωn^2\omega^2 = -n^2 - n^2\omega, giving (m2n2)+(2mnn2)ω(m^2 - n^2) + (2mn - n^2)\omega). Matching real and ω\omega-components and accounting for the units {1,ω,ω2,1,ω,ω2}\{1, \omega, \omega^2, -1, -\omega, -\omega^2\} yields the two families. The condition mn(mod3)m \equiv n \pmod{3} causes all three of a,b,ca, b, c (before division) to be divisible by 3, producing Family 2 after dividing by 3. \square

Lemma 1. (Scaling.) For each primitive triple (a0,b0,c0)(a_0, b_0, c_0) with primitive incircle radius r0r_0, the scaled triple (ka0,kb0,kc0)(ka_0, kb_0, kc_0) has incircle radius kr0kr_0. The number of valid scaled copies with rRr \leq R is R/r0\lfloor R / r_0 \rfloor.

Proof. r(ka0,kb0,kc0)=3k2a0b02k(a0+b0+c0)=kr0r(ka_0, kb_0, kc_0) = \frac{\sqrt{3} \cdot k^2 a_0 b_0}{2k(a_0 + b_0 + c_0)} = k \cdot r_0. \square

Lemma 2. (Multiplicity.) Each unordered pair {a,b}\{a, b\} with aba \neq b gives one triangle (the 60-degree angle is between sides aa and bb). If a=ba = b, the triangle is equilateral with all angles equal to 60 degrees, counted once. Additionally, (a,b)(a, b) and (b,a)(b, a) represent the same triangle, so each primitive triple with aba \neq b contributes twice in the parameterization (once as (a,b)(a, b) and once as (b,a)(b, a)).

Proof. The 60-degree angle is uniquely determined by the law of cosines given c2=a2ab+b2c^2 = a^2 - ab + b^2. The triangle is unchanged by swapping aa and bb. \square

Editorial

The upper bound on mm is determined by the constraint that the smallest primitive triple for given mm must have r0Rr_0 \leq R. We iterate over n from 1 to m-1. We then family 1: m not congruent to n mod 3. Finally, family 2: m congruent to n mod 3.

Pseudocode

for n from 1 to m-1
Family 1: m not congruent to n mod 3
Family 2: m congruent to n mod 3

Complexity Analysis

  • Time: O(B2)O(B^2) where BB is the upper bound on mm, determined by RR. Since r0=Θ(m)r_0 = \Theta(m) for the smallest triples, B=O(R)B = O(R). However, most (m,n)(m, n) pairs are pruned, so the effective work is significantly less.
  • Space: O(1)O(1) (no storage beyond loop variables).

Answer

75085391\boxed{75085391}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_195/solution.cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*
 * Problem 195: Inscribed Circles of Triangles with One Angle of 60 Degrees
 *
 * Count integer-sided triangles with one 60-degree angle whose incircle
 * radius r <= R = 10^5.
 *
 * Parameterization: for p > q > 0, gcd(p,q) = 1:
 *   a0 = p^2 + 2pq, b0 = 2pq + q^2, c0 = p^2 + pq + q^2
 *   If (p-q) % 3 == 0: divide all by 3
 *   r0 = sqrt(3)*a0*b0/(2*(a0+b0+c0))
 *   count += floor(R / r0) for each primitive triple
 *
 * Optimization: iterate q in outer loop (1, 2, ...) and p in inner loop.
 * For fixed q, as p grows, r0 grows roughly as sqrt(3)*p*q/(2*(something)).
 * We break when r0 > R for the minimum possible case.
 *
 * Actually, the key insight: r0 = sqrt(3)*a0*b0/(2*s) where s=a0+b0+c0.
 * For large p: a0 ~ p^2, b0 ~ 2pq, c0 ~ p^2, s ~ 2p^2+2pq
 * r0 ~ sqrt(3)*2p^3*q/(2*(2p^2+2pq)) = sqrt(3)*p^2*q/(2(p+q))
 * For large p >> q: r0 ~ sqrt(3)*p*q/2
 * So p <= 2R/(sqrt(3)*q) roughly.
 *
 * Answer: 75085391
 */

int main() {
    const double R = 100000.0;
    const double sqrt3 = sqrt(3.0);
    ll count = 0;

    // Outer loop: q from 1 to some max
    // For q, p ranges from q+1 up to about 2R/(sqrt3*q) + margin
    // q_max: when p = q+1 (minimum p), r0 is minimized. But even for
    // large q, with p = q+1, r0 ~ sqrt(3)*(q+1)*q/2 which must be <= R
    // So q <= about 2R/sqrt(3) ~ 115470 at most, but for large q we need
    // p very close to q, which gives small r0.
    // Actually for p = q+1, a0 = (q+1)^2 + 2(q+1)q = 3q^2+4q+1, b0 = 2(q+1)q+q^2 = 3q^2+2q
    // c0 = (q+1)^2+(q+1)q+q^2 = 3q^2+3q+1
    // sum = 9q^2+9q+2, r0 = sqrt(3)*(3q^2+4q+1)*(3q^2+2q)/(2*(9q^2+9q+2))
    // For large q: r0 ~ sqrt(3)*9q^4/(2*9q^2) = sqrt(3)*q^2/2
    // So q <= sqrt(2R/sqrt3) ~ 340

    int q_max = (int)sqrt(2.0 * R / sqrt3) + 100;

    for (int q = 1; q <= q_max; q++) {
        int p_max = (int)(2.0 * R / (sqrt3 * q)) + 100;
        for (int p = q + 1; p <= p_max; p++) {
            if (__gcd(p, q) != 1) continue;

            ll a0 = (ll)p * p + 2LL * p * q;
            ll b0 = 2LL * p * q + (ll)q * q;
            ll c0 = (ll)p * p + (ll)p * q + (ll)q * q;

            if ((p - q) % 3 == 0) {
                a0 /= 3;
                b0 /= 3;
                c0 /= 3;
            }

            double r0 = sqrt3 * (double)a0 * (double)b0 / (2.0 * (double)(a0 + b0 + c0));

            if (r0 > R) break;  // p increasing => r0 increasing for fixed q

            ll k = (ll)(R / r0);
            if (k >= 1) count += k;
        }
    }

    cout << count << endl;
    return 0;
}