All Euler problems
Project Euler

Counting Rectangles

By counting carefully, it can be verified that a rectangular grid that is 3 by 2 contains 18 rectangles. Find the area of the grid with the nearest number of rectangles to two million (T = 2,000,000).

Source sync Apr 19, 2026
Problem #0085
Level Level 03
Solved By 27,914
Languages C++, Python
Answer 2772
Length 372 words
geometryalgebrasearch

Problem Statement

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

By counting carefully it can be seen that a rectangular grid measuring \(3\) by \(2\) contains eighteen rectangles:

PIC

Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the nearest solution

Problem 85: Counting Rectangles

Mathematical Foundation

Rectangle Counting

Theorem 1 (Rectangle counting formula). An m×nm \times n grid contains exactly

R(m,n)=(m+12)(n+12)=m(m+1)2n(n+1)2R(m, n) = \binom{m+1}{2} \binom{n+1}{2} = \frac{m(m+1)}{2} \cdot \frac{n(n+1)}{2}

axis-aligned rectangles.

Proof. An m×nm \times n grid is delineated by m+1m + 1 vertical lines x0,x1,,xmx_0, x_1, \ldots, x_m and n+1n + 1 horizontal lines y0,y1,,yny_0, y_1, \ldots, y_n. Every axis-aligned rectangle is uniquely determined by a choice of two distinct vertical lines xi<xjx_i < x_j (for the left and right edges) and two distinct horizontal lines yk<yly_k < y_l (for the top and bottom edges). The number of such vertical pairs is (m+12)\binom{m+1}{2} and the number of horizontal pairs is (n+12)\binom{n+1}{2}. Since these choices are independent, the total count is their product. Expanding:

(m+12)=(m+1)m2=m(m+1)2,(n+12)=n(n+1)2.\binom{m+1}{2} = \frac{(m+1)m}{2} = \frac{m(m+1)}{2}, \qquad \binom{n+1}{2} = \frac{n(n+1)}{2}. \quad \square

Verification. For m=3m = 3, n=2n = 2: R(3,2)=342232=63=18R(3, 2) = \frac{3 \cdot 4}{2} \cdot \frac{2 \cdot 3}{2} = 6 \cdot 3 = 18. \checkmark

Search Space Reduction

Lemma 1 (Upper bound on mm). We may restrict the search to mm satisfying m(m+1)2T\frac{m(m+1)}{2} \le T, i.e., mO(T)m \le O(\sqrt{T}).

Proof. Since R(m,n)R(m,1)=m(m+1)2R(m, n) \ge R(m, 1) = \frac{m(m+1)}{2} for all n1n \ge 1 (as (n+12)1\binom{n+1}{2} \ge 1), once m(m+1)2>T\frac{m(m+1)}{2} > T we have R(m,n)>TR(m, n) > T for every n1n \ge 1. Moreover, RR is strictly increasing in both arguments, so all mmm' \ge m are likewise infeasible for producing a value closer to TT from below. The quadratic inequality m(m+1)/2Tm(m+1)/2 \le T yields m(1+1+8T)/2=O(T)m \le \lfloor(-1 + \sqrt{1 + 8T})/2\rfloor = O(\sqrt{T}). \square

Lemma 2 (Optimal nn for fixed mm). For fixed mm and target TT, the unique real root n>0n^* > 0 of R(m,n)=TR(m, n^*) = T satisfies

n=1+1+8T/[m(m+1)]2.n^* = \frac{-1 + \sqrt{1 + 8T/[m(m+1)]}}{2}.

The optimal integer nn is either n\lfloor n^* \rfloor or n\lceil n^* \rceil.

Proof. Setting R(m,n)=TR(m, n) = T yields m(m+1)2n(n+1)2=T\frac{m(m+1)}{2} \cdot \frac{n(n+1)}{2} = T, i.e., n2+n4Tm(m+1)=0n^2 + n - \frac{4T}{m(m+1)} = 0. By the quadratic formula, the positive root is as stated. Since R(m,n)R(m, n) is strictly increasing in nn (for n1n \ge 1), the function crosses the target TT between n\lfloor n^* \rfloor and n\lceil n^* \rceil, so one of these two integers minimizes R(m,n)T|R(m, n) - T|. \square

Editorial

The rectangle count factors into one triangular number from the horizontal direction and one from the vertical direction. That is what makes the search manageable: once one side length is fixed, the count becomes a strictly increasing quadratic in the other side.

So instead of testing every pair blindly, we iterate over one dimension and solve for the real value of the other dimension that would hit the target exactly. Because the count is monotone, the best integer width must lie right next to that real root. The candidates are therefore generated by the feasible heights and only a tiny neighborhood around the corresponding optimal width, which turns a two-dimensional search into an essentially one-dimensional one.

Pseudocode

Set the best difference to infinity and the best area to 0.

For each grid height m while its triangular factor does not already exceed the target:
    Compute the real width that would make the rectangle count equal to the target

    Examine the nearby integer widths around that real value
    For each such width:
        compute the exact rectangle count
        compare its distance from the target with the current best
        if it is better, record the new difference and the new area

Return the recorded best area.

Complexity Analysis

Time: O(T)O(\sqrt{T}). The outer loop runs while m(m+1)/2Tm(m+1)/2 \le T, giving m=O(T)m = O(\sqrt{T}). Each iteration performs O(1)O(1) arithmetic.

Space: O(1)O(1). Only a constant number of variables are maintained.

Answer

2772\boxed{2772}

Code

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

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

int main(){
    // Problem 85: Counting Rectangles
    // R(m,n) = C(m+1,2) * C(n+1,2) = m(m+1)/2 * n(n+1)/2
    // Find area m*n such that R(m,n) is closest to 2,000,000.
    // Answer: 2772

    long long target = 2000000;
    long long best_diff = LLONG_MAX;
    int best_area = 0;

    for(int m = 1; m * (m + 1) / 2 <= target; m++){
        long long tm = (long long)m * (m + 1) / 2;
        double val = 2.0 * target / tm;
        int n = (int)((-1.0 + sqrt(1.0 + 4.0 * val)) / 2.0);

        for(int nn = max(1, n - 1); nn <= n + 2; nn++){
            long long rects = tm * (long long)nn * (nn + 1) / 2;
            long long diff = abs(rects - target);
            if(diff < best_diff){
                best_diff = diff;
                best_area = m * nn;
            }
        }
    }

    cout << best_area << endl;

    return 0;
}