UVa 106 - Fermat vs. Pythagoras

106 - Fermat vs. Pythagoras

 * http://acm.uva.es/p/v1/106.html

Summary
We will need to find another relationship that generates the Pythagorean triples that will allow us to generate all pairs easily.

Explanation
This is a relatively difficult Math problem. The intuition is that we would brute force on x, y, and z would take too long. The easy optimization is that you can calculate z, but since x and y can be as big as a million, the $$O(n^2)$$ solution is still not good enough.

The actual solution takes a little bit of Number Theory.

Assume that you have two numbers, r, and s. (for now, assume they're given) Then this equation is true:

$$(r^2-s^2)^2 + (2rs)^2 = (r^2+s^2)^2$$

Given an r, s pair, it is trivial to create a Pythagorean triple. The difficult thing is to prove that all of them can be generated from them. If this is proven, then it is easy to generate all the triples, since we only have to check all $$r,s < \sqrt{n}$$.

Why does this generate all triples?

Let's assume that x,y,z is a triple which is relatively prime. This implies that one, but not both, of x,y must be even. (Otherwise, z would be divisible by 2, but not by 4) Assuming, without the loss of generality, that y is even, and x,z are odd, we can rewrite the equation as:

$$y^2 = (z+x)(z-x)$$

Since y is even, $$y^2$$ is divisible by 4. Also, note that z+x and z-x are both divisible by 2 (adding/subtracting an odd number to another odd number). So we can further write it as:

$$(\frac{y}{2})^2 = \frac{(z+x)}{2} \cdot \frac{(z-x)}{2}$$

Now $$\frac{z+x}{2}$$ and $$\frac{z-x}{2}$$ must be relatively prime (if they had a common factor, then their sum[z] and their difference[x] would have a common factor). It is now easy to see that each of these number must themselves be squares (thru unique factorization theorems). Setting $$r^2 = \frac{(z+x)}{2}$$ and $$s^2 = \frac{(z-x)}{2}$$, and you will finally reach the previous equation of:

$$(r^2-s^2)^2 + (2rs)^2 = (r^2+s^2)^2$$

Since $$\sqrt{ 1000000 } = 1000$$, we can use all r,s pair to generate the triples.

You can also prove that, x,y,z are relative prime iff r,s are relative prime. ( using that fact that R.PRIME(r,s) and one and only one of r,s is even number ==> R.PRIME(r+s, r-s) ). This can further reduce the run time.

Input
10 25 100 1000000

Output
1 4 4 9 16 27 159139 133926