UVA - 106 Fermat vs. Pythagoras

题意:起初推不出来,看了题解说其实就是勾股数组(毕达哥拉斯三元组)的证明,所以看了这个,摘抄了一些解释:

本原勾股数组(PPT)是一个三元组(a,b,c),其中a,b,c无公因数,且满足a² +b² =c²。

很明显存在无穷多个勾股数组(abc同乘以n),下面研究abc没有公因数的情况,先写出一些本原勾股数组:

case:(3,4,5) (5,12,13) (8,15,17) (7,24,25) (20,21,29)(9,40,41)(12,35,37)(11,60,61)(28,45,53) (33,56,65) (16,63,65)

观察可以看出a,b奇偶性不同且c总是奇数。(用一点技巧可以证明这是正确的)

另外:

3² = 5² - 4² = (5-4)(5+4) = 1 × 9

15² = 17²-8² = (17-8)(17+8) = 9 ×25

35² = 37² - 12² = (37-12)(37+12) = 25 ×49

......

很神奇的是似乎c-b与c+b总是平方数,并且c-b与c+b木有公因数。证明一下下:假设有公因数,设d是c-b与c+b的公因数,则d也整除(c+b)+(c-b)=2c, (c+b)-(c-b) = 2b,所以d整除2c,2b,但是b,c木有公因数,又假设了(a,b,c)是本原勾股数组,从而d等于1或2,又因为d整除(c-b)(c+b)=a².a²是奇数,所以d = 1,c-b与c+b木有公因数。,又因为(c-b)(c+b)=a²,所以c-b与c+b的积是平方数,只有二者都是平方数才会出现(可以把二者分解成素数乘积直观地看出),令c+b = s²,c-b=t²,解得

c=(s²+t²)/2, b=(s²-t²)/2,a = √(c-b)(c+b) = st.这就得出了勾股数组定理:

每个本原勾股数组(a,b,c)(a为奇数,b偶数)都可由如下公式得出:a=st,b=(s²-t²)/2, c = (s²+t²)/2, 其中s>t>=1是没有公因数的奇数。

当取t=1时就可以得到上面的许多例子。

接下来就是照着写就是了

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 1000010;

bool used[MAXN];
long long gcd(long long a,long long b){
    return b == 0?a:gcd(b,a%b);
}

int main(){
    long long n,a,b,c;
    long long count1,count2;
    while (scanf("%lld",&n) != EOF){
        count1 = count2 = 0;
        memset(used,0,sizeof(used));
        long long m = (long long)sqrt(n+0.5);
        for (long long t = 1; t <= m; t+=2)
            for (long long s = t + 2; s * t <= n; s+=2){
                if (gcd(s,t) == 1){
                    a = s * t;
                    b = (s * s - t * t) / 2;
                    c = (s * s + t * t) / 2;
                    if (c <= n){
                        count1++;
                        if (!used[a]){
                            count2++;
                            used[a] = 1;
                        }
                        if (!used[b]){
                            count2++;
                            used[b] = 1;
                        }
                        if (!used[c]){
                            count2++;
                            used[c] = 1;
                        }

                        for (int j = 2; c * j <= n; j++){
                            if(!used[a*j]){
                                count2++; 
                                used[a*j] = 1;
                            }
                            if(!used[b*j]){
                                count2++;
                                used[b*j] = 1;
                            }
                            if(!used[c*j]){
                                count2++;
                                used[c*j]=1;
                            }
                        }
                    }
                }
            }
        printf("%lld %lld\n",count1,n-count2);
    }
    return 0;
}



你可能感兴趣的:(UVA - 106 Fermat vs. Pythagoras)