All Euler problems
Project Euler

Pentagon Tilings

Study the enumeration of pentagonal tilings via Euler's pentagonal number theorem. The generalized pentagonal numbers omega_k = k(3k-1)/2 for k in Z govern the expansion of the Euler function prod_...

Source sync Apr 19, 2026
Problem #0891
Level Level 36
Solved By 182
Languages C++, Python
Answer 1541414
Length 309 words
sequenceanalytic_mathgeometry

Problem Statement

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

A round clock only has three hands: hour, minute, second. All hands look identical and move continuously. Moreover, there is no number or reference mark so that the "upright position" is unknown. The clock functions the same as a normal $12$-hour analogue clock.

Despite the inconvenient design, for most time it is possible to tell the correct time (within a $12$-hour cycle) from the clock, just by measuring accurately the angles between the hands. For example, if all three hands coincide, then the time must be $12:00:00$.

Nevertheless, there are several moments where the clock shows an ambiguous reading. For example, the following moment could be either $1:30:00$ or $7:30:00$ (with the clock rotated $180^\circ$). Thus both $1:30:00$ and $7:30:00$ are ambiguous moments. Note that even if two hands perfectly coincide, we can still see them as two distinct hands in the same position. Thus for example $3:00:00$ and $9:00:00$ are not ambiguous moments.

Problem illustration

How many ambiguous moments are there within a $12$-hour cycle?

Problem 891: Pentagon Tilings

Mathematical Foundation

Theorem 1 (Euler’s Pentagonal Number Theorem). For x<1|x| < 1,

n=1(1xn)=k=(1)kxk(3k1)/2.\prod_{n=1}^{\infty}(1-x^n) = \sum_{k=-\infty}^{\infty} (-1)^k x^{k(3k-1)/2}.

Proof. We use Franklin’s sign-reversing involution. Let Dn\mathcal{D}_n denote the set of partitions of nn into distinct parts. For λ=(λ1>λ2>>λm)Dn\lambda = (\lambda_1 > \lambda_2 > \cdots > \lambda_m) \in \mathcal{D}_n, define:

  • s(λ)=λms(\lambda) = \lambda_m (the smallest part),
  • σ(λ)\sigma(\lambda) = the length of the maximal “descending staircase” from the top, i.e., the largest jj such that λi=λ1i+1\lambda_i = \lambda_1 - i + 1 for i=1,,ji = 1, \ldots, j.

Define the involution φ ⁣:DnDn\varphi \colon \mathcal{D}_n \to \mathcal{D}_n as follows:

  • If s(λ)σ(λ)s(\lambda) \leq \sigma(\lambda) and s(λ)σ(λ)s(\lambda) \neq \sigma(\lambda) when s(λ)=σ(λ)+1s(\lambda) = \sigma(\lambda) + 1, then remove the smallest part and add 1 to each of the s(λ)s(\lambda) largest parts.
  • Otherwise, subtract 1 from each of the σ(λ)\sigma(\lambda) largest parts and insert a new part of size σ(λ)\sigma(\lambda).

When φ\varphi is defined, it changes the parity of mm (the number of parts), yielding cancellation. The fixed points satisfy s=σs = \sigma or s=σ+1s = \sigma + 1, corresponding to partitions with mm parts summing to m(3m±1)/2m(3m \pm 1)/2. Expanding (1xn)=λD(1)λxλ\prod(1-x^n) = \sum_{\lambda \in \mathcal{D}}(-1)^{|\lambda|}x^{|\lambda|} and applying the involution, only fixed-point contributions survive, giving the right-hand side. \square

Theorem 2 (Partition Function Recurrence). The partition function p(n)p(n) satisfies

p(n)=k=1ω±kn(1)k+1[p(nωk)+p(nωk)],p(n) = \sum_{\substack{k=1 \\ \omega_{\pm k} \leq n}}^{\infty} (-1)^{k+1}\bigl[p(n - \omega_k) + p(n - \omega_{-k})\bigr],

where ωk=k(3k1)/2\omega_k = k(3k-1)/2, ωk=k(3k+1)/2\omega_{-k} = k(3k+1)/2, p(0)=1p(0) = 1, and p(m)=0p(m) = 0 for m<0m < 0.

Proof. From the generating function identity (k(1)kxωk)(n0p(n)xn)=1\bigl(\sum_{k}(-1)^k x^{\omega_k}\bigr)\bigl(\sum_{n \geq 0} p(n)x^n\bigr) = 1, equate coefficients of xnx^n for n1n \geq 1:

p(n)+k1(1)k[p(nωk)+p(nωk)]=0.p(n) + \sum_{k \geq 1}(-1)^k\bigl[p(n-\omega_k) + p(n-\omega_{-k})\bigr] = 0.

Rearranging yields the stated recurrence. \square

Lemma (Pentagonal Number Growth). For k1k \geq 1, ωk=k(3k1)/2k\omega_k = k(3k-1)/2 \geq k, and the number of pentagonal numbers n\leq n is Θ(n)\Theta(\sqrt{n}).

Proof. Solving k(3k1)/2nk(3k-1)/2 \leq n gives k1+1+24n6=O(n)k \leq \frac{1+\sqrt{1+24n}}{6} = O(\sqrt{n}). Hence at most O(n)O(\sqrt{n}) terms are nonzero in the recurrence for p(n)p(n). \square

Theorem 3 (Hardy—Ramanujan Asymptotic). As nn \to \infty,

p(n)14n3exp ⁣(π2n3).p(n) \sim \frac{1}{4n\sqrt{3}} \exp\!\left(\pi\sqrt{\frac{2n}{3}}\right).

Proof. This was established by Hardy and Ramanujan (1918) using the circle method applied to the generating function p(n)xn=k1(1xk)1\sum p(n)x^n = \prod_{k \geq 1}(1-x^k)^{-1}. Rademacher (1937) refined the method into an exact convergent series. \square

Editorial

Euler pentagonal theorem, partition function recurrence. We compute p(0), p(1), …, p(n) via pentagonal recurrence. We enumerate the admissible parameter range, discard candidates that violate the derived bounds or arithmetic constraints, and update the final set or total whenever a candidate passes the acceptance test.

Pseudocode

Compute p(0), p(1), ..., p(n) via pentagonal recurrence
while true

Complexity Analysis

  • Time: O(nn)O(n\sqrt{n}), since for each i{1,,n}i \in \{1, \ldots, n\} the inner loop runs O(i)O(\sqrt{i}) iterations.
  • Space: O(n)O(n) for the array P[0..n]P[0..n].

Answer

1541414\boxed{1541414}

Code

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

C++ project_euler/problem_891/solution.cpp
/*
 * Problem 891: Pentagon Tilings
 * Euler's pentagonal theorem and partition function recurrence.
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

vector<ll> partition_function(int N) {
    vector<ll> p(N + 1, 0);
    p[0] = 1;
    for (int n = 1; n <= N; n++) {
        for (int k = 1; ; k++) {
            int w1 = k * (3*k - 1) / 2;
            int w2 = k * (3*k + 1) / 2;
            int sign = (k % 2 == 1) ? 1 : -1;
            if (w1 > n) break;
            p[n] += sign * p[n - w1];
            if (w2 <= n) p[n] += sign * p[n - w2];
        }
    }
    return p;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    auto p = partition_function(200);
    cout << "=== Partition Function ===" << endl;
    for (int n : {0,1,2,3,4,5,10,20,50,100,200})
        cout << "p(" << n << ") = " << p[n] << endl;

    cout << "\n=== Pentagonal Numbers ===" << endl;
    for (int k = 1; k <= 10; k++) {
        cout << "w(" << k << ") = " << k*(3*k-1)/2
             << ", w(" << -k << ") = " << k*(3*k+1)/2 << endl;
    }

    cout << "\nAnswer: p(100) = " << p[100] << endl;
    return 0;
}