A Pythagorean triple is defined as three positive integers 



(
a
,
b
,
c
)


{\displaystyle (a,b,c)}

 where 



a
<
b
<
c


{\displaystyle a<b<c}

, and 




a

2


+

b

2


=

c

2


.


{\displaystyle a^{2}+b^{2}=c^{2}.}



They are called primitive triples if 



a
,
b
,
c


{\displaystyle a,b,c}

 are co-prime, that is, if their pairwise greatest common divisors 





g
c
d


(
a
,
b
)
=


g
c
d


(
a
,
c
)
=


g
c
d


(
b
,
c
)
=
1


{\displaystyle {\rm {gcd}}(a,b)={\rm {gcd}}(a,c)={\rm {gcd}}(b,c)=1}

.

Because of their relationship through the Pythagorean theorem, a, b, and c are co-prime if a and b are co-prime (





g
c
d


(
a
,
b
)
=
1


{\displaystyle {\rm {gcd}}(a,b)=1}

).  

Each triple forms the length of the sides of a right triangle, whose perimeter is 



P
=
a
+
b
+
c


{\displaystyle P=a+b+c}

.



Task

The task is to determine how many Pythagorean triples there are with a perimeter no larger than 100 and the number of these that are primitive.



Extra credit
 
Deal with large values.   Can your program handle a maximum perimeter of 1,000,000?   What about 10,000,000?   100,000,000?

Note: the extra credit is not for you to demonstrate how fast your language is compared to others;   you need a proper algorithm to solve them in a timely manner.



Related tasks

   Euler's sum of powers conjecture 
   List comprehensions
   Pythagorean quadruples 


#include <cmath>
#include <iostream>
#include <numeric>
#include <tuple>
#include <vector>
 
using namespace std;
 
auto CountTriplets(unsigned long long maxPerimeter)
{
    unsigned long long totalCount = 0;
    unsigned long long primitveCount = 0;
    auto max_M = (unsigned long long)sqrt(maxPerimeter/2) + 1;
    for(unsigned long long m = 2; m < max_M; ++m)
    {
        for(unsigned long long n = 1 + m % 2; n < m; n+=2)
        {
            if(gcd(m,n) != 1)
            {
                continue;
            }
 
            // The formulas below will generate primitive triples if:
            //   0 < n < m
            //   m and n are relatively prime (gcd == 1)
            //   m + n is odd
 
            auto a = m * m - n * n;
            auto b = 2 * m * n;
            auto c = m * m + n * n;
            auto perimeter = a + b + c;
            if(perimeter <= maxPerimeter)
            {
                primitveCount++;
                totalCount+= maxPerimeter / perimeter;
            }
        }
    }
 
    return tuple(totalCount, primitveCount);
}
 
 
int main()
{
    vector<unsigned long long> inputs{100, 1000, 10'000, 100'000,
        1000'000, 10'000'000, 100'000'000, 1000'000'000,
        10'000'000'000};  // This last one takes almost a minute
    for(auto maxPerimeter : inputs)
    {
        auto [total, primitive] = CountTriplets(maxPerimeter);
        cout << "\nMax Perimeter: " << maxPerimeter << ", Total: " << total << ", Primitive: " << primitive ;
    }
}
 