Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

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

All Problems

Problem 688: Piles of Plates

View on Project Euler

Project Euler Problem 688 Solution

EulerSolve provides an optimized solution for Project Euler Problem 688, Piles of Plates, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary Consider plate layouts whose pile heights are consecutive positive integers. If a layout uses exactly \(k\) piles and the smallest pile has height \(a \ge 1\), then the heights are $a,\ a+1,\ a+2,\ \dots,\ a+k-1.$ The total number of plates in that layout is therefore $ka+\frac{k(k-1)}{2}.$ For a limit \(n\), let \(f(n,k)\) count the valid layouts with exactly \(k\) piles and total at most \(n\). Then $f(n,k)=\max\left(0,\left\lfloor\frac{n-\frac{k(k-1)}{2}}{k}\right\rfloor\right).$ Now define $F(n)=\sum_{k\ge 1} f(n,k),\qquad S(N)=\sum_{n=1}^{N}F(n).$ The goal is to compute \(S(10^{16}) \bmod (10^9+7)\). A direct enumeration over \(n\), \(k\), and the starting height \(a\) would be far too slow, so the solution rewrites the count as a closed floor-sum over \(k\). Mathematical Approach Write $\Delta_k=\frac{k(k-1)}{2}.$ This is the extra number of plates forced by the consecutive increase \(0,1,\dots,k-1\) once the smallest pile height is fixed. Step 1: Count layouts for fixed \(n\) and fixed \(k\) If the smallest pile has height \(a\), the total is \(ka+\Delta_k\)....

Detailed mathematical approach

Problem Summary

Consider plate layouts whose pile heights are consecutive positive integers. If a layout uses exactly \(k\) piles and the smallest pile has height \(a \ge 1\), then the heights are

$a,\ a+1,\ a+2,\ \dots,\ a+k-1.$

The total number of plates in that layout is therefore

$ka+\frac{k(k-1)}{2}.$

For a limit \(n\), let \(f(n,k)\) count the valid layouts with exactly \(k\) piles and total at most \(n\). Then

$f(n,k)=\max\left(0,\left\lfloor\frac{n-\frac{k(k-1)}{2}}{k}\right\rfloor\right).$

Now define

$F(n)=\sum_{k\ge 1} f(n,k),\qquad S(N)=\sum_{n=1}^{N}F(n).$

The goal is to compute \(S(10^{16}) \bmod (10^9+7)\). A direct enumeration over \(n\), \(k\), and the starting height \(a\) would be far too slow, so the solution rewrites the count as a closed floor-sum over \(k\).

Mathematical Approach

Write

$\Delta_k=\frac{k(k-1)}{2}.$

This is the extra number of plates forced by the consecutive increase \(0,1,\dots,k-1\) once the smallest pile height is fixed.

Step 1: Count layouts for fixed \(n\) and fixed \(k\)

If the smallest pile has height \(a\), the total is \(ka+\Delta_k\). Therefore the admissible values of \(a\) satisfy

$ka+\Delta_k\le n.$

Equivalently,

$a\le \frac{n-\Delta_k}{k}.$

Since \(a\) must be a positive integer, the number of choices is exactly

$f(n,k)=\max\left(0,\left\lfloor\frac{n-\Delta_k}{k}\right\rfloor\right).$

This already explains why large \(k\) values disappear quickly: once \(\Delta_k\) is close to \(n\), there is no room left for even the smallest possible first pile.

Step 2: Swap the order of summation

Instead of computing \(F(n)\) for each \(n\) and then adding, sum over the number of piles first:

$S(N)=\sum_{n=1}^{N}\sum_{k\ge 1} f(n,k)=\sum_{k\ge 1}\sum_{n=1}^{N} f(n,k).$

For a fixed \(k\), substitute the formula from Step 1:

$\sum_{n=1}^{N} f(n,k)=\sum_{n=1}^{N}\max\left(0,\left\lfloor\frac{n-\Delta_k}{k}\right\rfloor\right).$

Now shift the index by setting \(m=n-\Delta_k\). Terms with \(m<k\) contribute \(0\), so the whole block becomes

$\sum_{m=0}^{N-\Delta_k}\left\lfloor\frac{m}{k}\right\rfloor,$

with the understanding that this contribution is zero if \(N\le \Delta_k\).

Step 3: Evaluate the floor-sum in closed form

Let

$M=N-\Delta_k.$

If \(M>0\), divide it by \(k\):

$M=uk+v,\qquad 0\le v<k.$

Then the values of \(\left\lfloor m/k\right\rfloor\) appear in blocks:

$\underbrace{0,\dots,0}_{k\text{ terms}},\ \underbrace{1,\dots,1}_{k\text{ terms}},\ \dots,\ \underbrace{u-1,\dots,u-1}_{k\text{ terms}},\ \underbrace{u,\dots,u}_{v+1\text{ terms}}.$

Therefore

$\sum_{m=0}^{M}\left\lfloor\frac{m}{k}\right\rfloor =k\sum_{j=0}^{u-1} j + u(v+1) =k\frac{u(u-1)}{2}+u(v+1).$

This removes the inner sum completely.

Step 4: Assemble the final formula

For every \(k\) with \(\Delta_k<N\), define \(u_k\) and \(v_k\) by

$N-\Delta_k=u_k k+v_k,\qquad 0\le v_k<k.$

Then

$\boxed{S(N)=\sum_{\substack{k\ge 1\\ \Delta_k<N}}\left(k\frac{u_k(u_k-1)}{2}+u_k(v_k+1)\right)\pmod{10^9+7}.}$

Once \(\Delta_k\ge N\), all later terms vanish. Since \(\Delta_k\sim k^2/2\), only \(O(\sqrt{N})\) values of \(k\) need to be examined.

Worked Example

For a local example, take \(n=14\) and \(k=3\). The possible layouts have heights

$1,2,3;\qquad 2,3,4;\qquad 3,4,5,$

with totals \(6,9,12\). The next starting height would give \(4+5+6=15>14\), so

$f(14,3)=3.$

The formula agrees:

$\Delta_3=\frac{3\cdot 2}{2}=3,\qquad \left\lfloor\frac{14-3}{3}\right\rfloor=3.$

For a cumulative example, take \(N=10\). The nonzero contributions are

$\begin{aligned} k=1&:&&\Delta_1=0,\ M=10=10\cdot 1+0,\ &&55,\\ k=2&:&&\Delta_2=1,\ M=9=4\cdot 2+1,\ &&20,\\ k=3&:&&\Delta_3=3,\ M=7=2\cdot 3+1,\ &&7,\\ k=4&:&&\Delta_4=6,\ M=4=1\cdot 4+0,\ &&1. \end{aligned}$

For \(k\ge 5\), the contribution is zero. Hence

$S(10)=55+20+7+1=83.$

How the Code Works

The C++, Python, and Java implementations all follow the same formula. They iterate over \(k=1,2,3,\dots\), compute the triangular offset \(\Delta_k=k(k-1)/2\), and stop as soon as \(\Delta_k\ge N\).

For each surviving \(k\), the implementation forms \(M=N-\Delta_k\), performs one integer division by \(k\), and obtains the quotient and remainder needed for

$k\frac{u(u-1)}{2}+u(v+1).$

Because the final answer is required modulo \(10^9+7\), the division by \(2\) is handled by multiplying with the modular inverse of \(2\). Every contribution is reduced modulo \(10^9+7\) before being added to the running total.

The C++ implementation also uses a wider integer type for intermediate products so that multiplying values near the \(10^{16}\) scale remains safe before the modular reduction. In addition, one implementation checks the closed formula against a tiny brute-force computation at \(N=100\), where both methods produce \(12656\).

Complexity Analysis

The loop stops when \(k(k-1)/2\ge N\), so the number of iterations is \(O(\sqrt{N})\). Each iteration performs only constant-time arithmetic: one triangular-number computation, one subtraction, one division with remainder, a handful of modular multiplications, and one modular addition. Therefore the total running time is \(O(\sqrt{N})\), and the extra memory usage is \(O(1)\).

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=688
  2. Triangular number: Wikipedia - Triangular number
  3. Arithmetic progression: Wikipedia - Arithmetic progression
  4. Floor and ceiling functions: Wikipedia - Floor and ceiling functions
  5. Modular arithmetic: Wikipedia - Modular arithmetic

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

Previous: Problem 687 · All Project Euler solutions · Next: Problem 689

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