-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy patheuler-0085.cpp
More file actions
94 lines (85 loc) · 3.02 KB
/
euler-0085.cpp
File metadata and controls
94 lines (85 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// ////////////////////////////////////////////////////////
// # Title
// Counting rectangles
//
// # URL
// https://projecteuler.net/problem=85
// http://euler.stephan-brumme.com/85/
//
// # Problem
// By counting carefully it can be seen that a rectangular grid measuring 3 by 2 contains eighteen rectangles:
//
// 
//
// Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the nearest solution.
//
// # Solved by
// Stephan Brumme
// March 2017
//
// # Algorithm
// When you look at the "one-dimensional" case (an area with only 1 row):
// || 3 || 6 || 4 ||
// || area || rectangles || total ||
// || 1x1 || 1 || 1 ||
// || 2x1 || 2+1 || 3 ||
// || 3x1 || 3+2+1 || 6 ||
// || 4x1 || 4+3+2+1 || 10 ||
//
// These are the triangle numbers `T(x) = x * dfrac{x+1}{2}`, see https://en.wikipedia.org/wiki/Triangular_number
// The same pattern appears in the 2D case with more than 1 row.
// An area `A` contains:
// `A(x,y) = T(x) * T(y) = dfrac{x(x+1)}{2} * dfrac{y(y+1)}{2}`
//
// `= dfrac{1}{4} xy * (x+1)(y+1)`
//
// Under the assumption that `y > x` I iterate over all `x` and `y` until I find the first area exceeding the limit.
// Each subsequent grid can't yield a better solution because of `A(x,y+1) > A(x,y)`.
//
// The grid with the nearest solution is the grid where the number of rectangles `r` is is closest to 2000000, i.e. where `abs(r - 2000000)` is minimized.
#include <iostream>
#include <cmath>
int main()
{
unsigned int tests = 1;
std::cin >> tests;
while (tests--)
{
unsigned int target = 2000000;
std::cin >> target;
// assume x <= y, therefore x <= sqrt(limit)
unsigned int root = sqrt(target);
unsigned int bestRectangles = 0;
unsigned int bestArea = 0;
for (unsigned int x = 1; x <= root + 1; x++) // allow slight overshooting
{
// start with a sqaure
unsigned int y = x;
// number of rectangles
unsigned int rectangles = 0;
// slowly increase y until too many rectangle in the grid
do
{
unsigned int area = x * y;
// the formula derived above
rectangles = x * (x + 1) * y * (y + 1) / 4;
// closer to desired number of rectangles than before ?
if (abs(bestRectangles - target) > abs(rectangles - target))
{
bestRectangles = rectangles;
bestArea = area;
}
// prefer larger areas, too (additional requirement of Hackerrank)
if (abs(bestRectangles - target) == abs(rectangles - target) && bestArea < area)
bestArea = area;
y++;
} while (rectangles < target);
// just a speed-up ... abortion when the inner loop exited with a square area x*y
// => it means that no further solutions possible, area already too large
if (y == x + 1) // plus one because y was incremented before leaving the inner loop
break;
}
std::cout << bestArea << std::endl;
}
return 0;
}