All Euler problems
Project Euler

Laserbeam

Three mirrors are arranged in the shape of an equilateral triangle, with their reflective surfaces pointing inwards. There is an infinitesimal gap at each vertex through which a laser beam may pass...

Source sync Apr 19, 2026
Problem #0202
Level Level 09
Solved By 2,977
Languages C++, Python
Answer 1209002624
Length 540 words
modular_arithmeticnumber_theorygraph

Problem Statement

This archive keeps the full statement, math, and original media on the page.

Three mirrors are arranged in the shape of an equilateral triangle, with their reflective surfaces pointing inwards. There is an infinitesimal gap at each vertex of the triangle through which a laser beam may pass.

Label the vertices \(A\), \(B\) and \(C\). There are \(2\) ways in which a laser beam may enter vertex \(C\), bounce off \(11\) surfaces, then exit through the same vertex: one way is shown below; the other is the reverse of that.

PIC

There are \(80840\) ways in which a laser beam may enter vertex \(C\), bounce off \(1000001\) surfaces, then exit through the same vertex.

In how many ways can a laser beam enter at vertex \(C\), bounce off \(12017639147\) surfaces, then exit through the same vertex?

Problem 202: Laserbeam

Mathematical Foundation

Theorem (Unfolding Principle). A laser beam making RR reflections inside an equilateral triangle corresponds, via the standard unfolding technique, to a straight line in the triangular tessellation of the plane. The line starts at the origin and terminates at a lattice point (a,b)(a, b) in the oblique coordinate system, where a+b=na + b = n with n=(R+3)/2n = (R + 3)/2.

Proof. Each reflection off a mirror wall is equivalent to reflecting the triangle across that wall and continuing the beam in a straight line. After RR reflections, the beam has crossed RR triangle edges. The beam enters at vertex CC and must exit at a vertex, crossing RR edges total. In the oblique coordinate system where the three families of parallel lines in the tessellation are indexed by coordinates (a,b)(a, b) with a+b=na + b = n, the number of edge crossings for a line from (0,0)(0,0) to (a,b)(a,b) is a+b2+adjustments for the entry/exita + b - 2 + \text{adjustments for the entry/exit}. Careful accounting (the beam enters through a gap, so the first and last crossings are at vertices, not interior edges) yields n=(R+3)/2n = (R + 3)/2. For R=12017639147R = 12017639147, we get n=6008819575n = 6008819575. \square

Theorem (Exit Vertex Classification). The beam exits through vertex CC if and only if b≢0(mod3)b \not\equiv 0 \pmod{3} and a≢0(mod3)a \not\equiv 0 \pmod{3}, which (given a+b=na + b = n with n1(mod3)n \equiv 1 \pmod{3}) is equivalent to b2(mod3)b \equiv 2 \pmod{3}.

Proof. In the triangular tessellation, a lattice point (a,b)(a, b) corresponds to a copy of vertex AA, BB, or CC depending on the residues of aa and bb modulo 3. Specifically, the point is a copy of CC when (amod3,bmod3){(0,1),(1,0),(2,2)}(a \bmod 3, b \bmod 3) \in \{(0,1),(1,0),(2,2)\}… More precisely, the vertex type cycles with period 3 along each axis. Since n=a+b1(mod3)n = a + b \equiv 1 \pmod{3} and we require the endpoint to be a copy of CC (not AA or BB), the condition reduces to b2(mod3)b \equiv 2 \pmod{3} (equivalently a2(mod3)a \equiv 2 \pmod{3}). One can verify this directly for small cases. \square

Theorem (No Intermediate Vertex Condition). The beam passes through no intermediate vertex (and thus does not exit prematurely) if and only if gcd(a,b)=1\gcd(a, b) = 1, equivalently gcd(b,n)=1\gcd(b, n) = 1.

Proof. If d=gcd(a,b)>1d = \gcd(a, b) > 1, then the lattice point (a/d,b/d)(a/d, b/d) lies on the line segment from (0,0)(0,0) to (a,b)(a,b) and corresponds to a vertex of the tessellation. The beam would exit through that vertex before reaching (a,b)(a,b). Conversely, if gcd(a,b)=1\gcd(a,b) = 1, no intermediate lattice point lies on the segment. Since a=nba = n - b, we have gcd(a,b)=gcd(nb,b)=gcd(n,b)\gcd(a,b) = \gcd(n-b, b) = \gcd(n, b). \square

Theorem (Counting via Mobius Inversion). The number of valid beam paths is:

Count=dnμ(d)C(d)\text{Count} = \sum_{d \mid n} \mu(d) \cdot C(d)

where C(d)=#{b[1,n1]:db,  b2(mod3)}C(d) = \#\{b \in [1, n-1] : d \mid b,\; b \equiv 2 \pmod{3}\}, and μ\mu is the Mobius function.

Proof. We seek #{b[1,n1]:gcd(b,n)=1,  b2(mod3)}\#\{b \in [1, n-1] : \gcd(b, n) = 1,\; b \equiv 2 \pmod{3}\}. By Mobius inversion, dgcd(b,n)μ(d)=[gcd(b,n)=1]\sum_{d \mid \gcd(b,n)} \mu(d) = [\gcd(b,n) = 1]. Exchanging the order of summation:

Count=b=1n1[gcd(b,n)=1][b2 ⁣ ⁣(mod3)]=dnμ(d)b=1db,b2(mod3)n11=dnμ(d)C(d).\text{Count} = \sum_{b=1}^{n-1} [\gcd(b,n)=1][b \equiv 2 \!\!\pmod{3}] = \sum_{d \mid n} \mu(d) \sum_{\substack{b=1 \\ d \mid b,\; b \equiv 2 \pmod{3}}}^{n-1} 1 = \sum_{d \mid n} \mu(d) \cdot C(d).

For each squarefree divisor dd of nn with gcd(d,3)=1\gcd(d, 3) = 1, substituting b=dkb = dk gives k[1,n/d1]k \in [1, n/d - 1] with dk2(mod3)dk \equiv 2 \pmod{3}, i.e., k2d1(mod3)k \equiv 2d^{-1} \pmod{3}, yielding C(d)=(n/d1r)/3+1C(d) = \lfloor(n/d - 1 - r)/3\rfloor + 1 where r=2d1mod3r = 2d^{-1} \bmod 3. \square

Lemma (Factorization). n=6008819575=52×11×17×23×29×41×47.n = 6008819575 = 5^2 \times 11 \times 17 \times 23 \times 29 \times 41 \times 47. Since 3n3 \nmid n, all 27=1282^7 = 128 squarefree divisors contribute.

Proof. Verified by trial division. Since 52n5^2 \mid n, the Mobius function μ(d)=0\mu(d) = 0 for any dd divisible by 525^2, but we enumerate over squarefree divisors constructed from {5,11,17,23,29,41,47}\{5, 11, 17, 23, 29, 41, 47\}. \square

Editorial

A laser beam enters vertex C of an equilateral triangle with mirrored sides, reflects exactly 12017639147 times off the internal surfaces, and exits through vertex C. Count the number of distinct beam paths. Approach: n = 6008819575 = 5^2 * 11 * 17 * 23 * 29 * 41 * 47. We factor n: primes = [5, 11, 17, 23, 29, 41, 47]. We then iterate over each subset T of primes. Finally, return count.

Pseudocode

Input: R = 12017639147
Output: number of valid laser paths
n = (R + 3) / 2 = 6008819575
Factor n: primes = [5, 11, 17, 23, 29, 41, 47]
count = 0
For each subset T of primes:
Return count

Complexity Analysis

  • Time: O(n)O(\sqrt{n}) for factorization, plus O(2k)O(2^k) for the Mobius sum where k=7k = 7 is the number of distinct prime factors. The Mobius summation is O(128)O(128), dominated by factorization at O(n)O(77,500)O(\sqrt{n}) \approx O(77{,}500).
  • Space: O(k)=O(7)O(k) = O(7) to store the prime factors.

Answer

1209002624\boxed{1209002624}

Code

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

C++ project_euler/problem_202/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main(){
    // PE 202: Laser beam in equilateral triangle, R = 12017639147 reflections.
    // n = (R + 3) / 2 = 6008819575.
    // Count b in [1, n-1] with b ≡ 2 mod 3 and gcd(b, n) = 1.
    // Use Mobius inversion over squarefree divisors of n.

    long long R = 12017639147LL;
    long long n = (R + 3) / 2;  // 6008819575

    // Factor n
    vector<long long> primes;
    {
        long long tmp = n;
        for(long long p = 2; p * p <= tmp; p++){
            if(tmp % p == 0){
                primes.push_back(p);
                while(tmp % p == 0) tmp /= p;
            }
        }
        if(tmp > 1) primes.push_back(tmp);
    }

    int np = primes.size();
    long long ans = 0;

    for(int mask = 0; mask < (1 << np); mask++){
        long long d = 1;
        int bits = __builtin_popcount(mask);
        long long mu = (bits % 2 == 0) ? 1 : -1;
        for(int i = 0; i < np; i++){
            if(mask & (1 << i)) d *= primes[i];
        }

        if(n % d != 0) continue; // d must divide n

        long long nd = n / d;
        long long d_mod3 = d % 3;
        long long cnt = 0;

        if(d_mod3 == 0){
            // 3 | d => d*k ≡ 0 mod 3 ≠ 2. No valid k.
            cnt = 0;
        } else {
            long long dinv3 = (d_mod3 == 1) ? 1 : 2;
            long long r = (2 * dinv3) % 3;
            long long upper = nd - 1;
            if(r == 0){
                if(upper >= 3)
                    cnt = (upper - 3) / 3 + 1;
            } else {
                if(upper >= r)
                    cnt = (upper - r) / 3 + 1;
            }
        }

        ans += mu * cnt;
    }

    cout << ans << endl;
    return 0;
}