Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

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

All Problems

Problem 842: Irregular Star Polygons

View on Project Euler

Project Euler Problem 842 Solution

EulerSolve provides an optimized solution for Project Euler Problem 842, Irregular Star Polygons, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary For each \(n\), place the vertices of a regular \(n\)-gon on a circle and draw polygon edges as straight chords. The quantity \(T(n)\) is obtained by looking at every interior point where diagonals meet, counting how many undirected Hamiltonian cycles on the same \(n\) vertices use at least two diagonals through that point, and then summing those contributions over all such points. The overall task is to evaluate $\sum_{n=3}^{60} T(n)\pmod{10^9+7}.$ The key observation is that the computation separates cleanly into a geometric part, which classifies intersection points by how many diagonals pass through them, and a combinatorial part, which counts cycles containing selected diagonals. Mathematical Approach Write \(M=10^9+7\). For a fixed \(n\), let \(P_n(r)\) denote the number of interior intersection points through which exactly \(r\) diagonals of the regular \(n\)-gon pass. The whole problem reduces to computing \(P_n(r)\) and then weighting each class by the number of Hamiltonian cycles that use at least two of those \(r\) diagonals. Step 1: Classify Interior Intersection Points Take indices \(a<b<c<d\). In a convex \(n\)-gon, the diagonals joining \(a\) to \(c\) and \(b\) to \(d\) cross at exactly one interior point. So every ordered quadruple \(a<b<c<d\) contributes one diagonal-intersection event....

Detailed mathematical approach

Problem Summary

For each \(n\), place the vertices of a regular \(n\)-gon on a circle and draw polygon edges as straight chords. The quantity \(T(n)\) is obtained by looking at every interior point where diagonals meet, counting how many undirected Hamiltonian cycles on the same \(n\) vertices use at least two diagonals through that point, and then summing those contributions over all such points.

The overall task is to evaluate

$\sum_{n=3}^{60} T(n)\pmod{10^9+7}.$

The key observation is that the computation separates cleanly into a geometric part, which classifies intersection points by how many diagonals pass through them, and a combinatorial part, which counts cycles containing selected diagonals.

Mathematical Approach

Write \(M=10^9+7\). For a fixed \(n\), let \(P_n(r)\) denote the number of interior intersection points through which exactly \(r\) diagonals of the regular \(n\)-gon pass. The whole problem reduces to computing \(P_n(r)\) and then weighting each class by the number of Hamiltonian cycles that use at least two of those \(r\) diagonals.

Step 1: Classify Interior Intersection Points

Take indices \(a<b<c<d\). In a convex \(n\)-gon, the diagonals joining \(a\) to \(c\) and \(b\) to \(d\) cross at exactly one interior point. So every ordered quadruple \(a<b<c<d\) contributes one diagonal-intersection event.

If a point \(P\) is the common intersection of exactly \(r\) diagonals, then every pair of those diagonals determines one quadruple, and every such quadruple leads back to the same point. Therefore the number of quadruples producing \(P\) is

$q=\binom{r}{2}.$

This means that once equal geometric intersections have been grouped together, the concurrency \(r\) is recovered from the bucket size \(q\) by

$r=\frac{1+\sqrt{1+8q}}{2}.$

So the geometric layer does not need any deeper polygon theory: it is enough to enumerate all quadruples, group identical intersection coordinates, and convert each bucket size into a concurrency class \(r\).

Step 2: Count Cycles Containing a Fixed Set of Diagonals

Now fix one interior point \(P\) with concurrency \(r\). Any diagonals passing through the same interior point are pairwise disjoint as edges of the polygon: if two of them shared a vertex, they would meet on the boundary instead of in the interior.

For \(t\in\{0,1,\dots,r\}\), let \(A_n(t)\) be the number of undirected Hamiltonian cycles on the \(n\) labeled vertices that contain some fixed set of \(t\) diagonals through \(P\).

When \(t=0\), this is simply the number of Hamiltonian cycles in the complete graph on \(n\) labeled vertices:

$A_n(0)=\frac{(n-1)!}{2}.$

When \(t\ge 1\), contract each forced diagonal into a single block. Since the chosen diagonals are disjoint, this reduces the \(n\) vertices to \(n-t\) units. An undirected cyclic ordering of those units contributes

$\frac{(n-t-1)!}{2}$

possibilities, and each contracted diagonal can be traversed in two directions. Hence

$A_n(t)=2^t\cdot \frac{(n-t-1)!}{2}=(n-t-1)!\,2^{t-1}\qquad (t\ge 1).$

This is exactly the counting rule used by the implementations.

Step 3: Use Inclusion-Exclusion to Enforce "At Least Two"

For a point with \(r\) available diagonals, let \(B_n(r)\) be the number of Hamiltonian cycles that use none of them. Standard inclusion-exclusion over the \(r\) forbidden diagonals gives

$B_n(r)=\sum_{t=0}^{r}(-1)^t\binom{r}{t}A_n(t).$

Next let \(C_n(r)\) be the number of Hamiltonian cycles that use exactly one of those \(r\) diagonals. Choose which diagonal is used, then exclude the remaining \(r-1\) diagonals by another inclusion-exclusion step:

$C_n(r)=r\sum_{t=0}^{r-1}(-1)^t\binom{r-1}{t}A_n(t+1).$

If \(D_n(r)\) denotes the number of Hamiltonian cycles that use at least two diagonals through the point, then

$D_n(r)=A_n(0)-B_n(r)-C_n(r).$

This formula is the combinatorial core of the solution.

Step 4: Combine Geometric and Combinatorial Layers

Once the regular \(n\)-gon has been partitioned into concurrency classes, the total contribution for that \(n\) is

$T(n)=\sum_{r\ge 2} P_n(r)\,D_n(r)\pmod{M}.$

The lower bound \(r\ge 2\) is natural: an interior crossing point only matters when at least two diagonals pass through it. Each class contributes independently, so the program can first discover the multiplicities \(P_n(r)\) and then apply the same combinatorial formula to every observed \(r\).

Worked Example: \(n=5\)

In a regular pentagon there are five interior diagonal intersections, and each one is formed by exactly two diagonals. Therefore

$P_5(2)=5.$

The unrestricted number of undirected Hamiltonian cycles is

$A_5(0)=\frac{4!}{2}=12.$

For one fixed diagonal through a chosen intersection point,

$A_5(1)=(5-2)!\,2^0=6,$

and for both diagonals through that point,

$A_5(2)=(5-3)!\,2^1=4.$

So

$B_5(2)=A_5(0)-2A_5(1)+A_5(2)=12-12+4=4,$

$C_5(2)=2\bigl(A_5(1)-A_5(2)\bigr)=2(6-4)=4,$

and therefore

$D_5(2)=12-4-4=4.$

Multiplying by the five intersection points gives

$T(5)=P_5(2)D_5(2)=5\cdot 4=20,$

which matches the small check embedded in the solver.

How the Code Works

The C++ implementation precomputes factorials, inverse factorials, and powers of \(2\) modulo \(10^9+7\) up to \(60\). That makes binomial coefficients and the values \(A_n(t)\) constant-time operations during the main loop.

For each \(n\), it places the vertices on the unit circle using high-precision trigonometric values, enumerates every quadruple \(a<b<c<d\), and computes the intersection of diagonals \(ac\) and \(bd\). Each intersection coordinate is scaled and rounded to a stable integer key so that coincident points fall into the same bucket.

After that grouping step, each bucket size \(q\) is converted to a concurrency value \(r\) through the triangular-number identity \(q=\binom{r}{2}\). The implementation then evaluates the inclusion-exclusion formulas above to obtain \(D_n(r)\), multiplies by the number of points in that class, and accumulates \(T(n)\) modulo \(10^9+7\).

The C++ implementation performs the full numeric computation directly. The Python and Java implementations delegate to that same compiled computation and only parse the final printed result.

Complexity Analysis

For a fixed \(n\), the geometric stage examines every quadruple of vertices, so its running time is \(O(n^4)\). The intersection-grouping table stores one entry per distinct interior point, so the memory usage is \(O(U_n)\), where \(U_n\le \binom{n}{4}\).

The combinatorial stage is much smaller. The modular precomputation is \(O(n)\), and evaluating the inclusion-exclusion sums over the possible concurrency classes is at worst \(O(n^2)\) for one value of \(n\). Therefore the geometric enumeration dominates the total cost.

Across the full range \(3\le n\le 60\), the runtime is dominated by

$\sum_{n=3}^{60} O(n^4),$

which is entirely practical for this fixed bound.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=842
  2. Inclusion-exclusion principle: Wikipedia - Inclusion-exclusion principle
  3. Hamiltonian cycle: Wikipedia - Hamiltonian cycle
  4. Regular polygon: Wikipedia - Regular polygon
  5. Line-line intersection: Wikipedia - Line-line intersection

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

Previous: Problem 841 · All Project Euler solutions · Next: Problem 843

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! 🧮