-
Notifications
You must be signed in to change notification settings - Fork 0
/
day 69
71 lines (63 loc) · 1.66 KB
/
day 69
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
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
// find greatest common divisor
template <typename T>
T gcd(T a, T b)
{
while (a != 0)
{
T c = a;
a = b % a;
b = c;
}
return b;
}
int main()
{
// pre-computation step 1: find all triangle combinations up to 1500000
const unsigned int MaxLength = 5 * 1000 * 1000;
// [length] => [number of valid combinations]
std::vector<unsigned int> combinations(MaxLength, 0);
for (unsigned int m = 2; m < sqrt(MaxLength); m++)
for (unsigned int n = 1; n < m; n++)
{
// only valid m and n
if ((m + n) % 2 != 1)
continue;
if (gcd(m, n) != 1)
continue;
// compute basic triplet
auto a = m*m - n*n;
auto b = 2*m*n;
auto c = m*m + n*n;
auto sum = a + b + c;
// and all of its multiples
unsigned int k = 1;
while (k*sum <= MaxLength)
{
combinations[k*sum]++;
k++;
}
}
// pre-computation step 2: extract those with exactly one combination
std::vector<unsigned int> once;
for (size_t i = 0; i < combinations.size(); i++)
if (combinations[i] == 1)
once.push_back(i);
// running the test-cases is a simple look-up
unsigned int tests = 1;
std::cin >> tests;
while (tests--)
{
unsigned int limit = 1500000;
std::cin >> limit;
// find first triangle perimeter exceeding 1500000 with exactly one combination
auto pos = std::upper_bound(once.begin(), once.end(), limit);
// count how many one-combo-triangles are smaller
auto result = std::distance(once.begin(), pos);
// and print that number
std::cout << result << std::endl;
}
}