1. 程式人生 > >UVA106- Fermat vs. Pythagoras(素勾股數)

UVA106- Fermat vs. Pythagoras(素勾股數)

題意:給你一個n,讓你找出一些勾股陣列,a^2+b^2=c^2 , 需要滿足a<b<c<=n 。 對於每個case題目首先需要你輸出這些勾股陣列中素勾股數T的個數,然後再輸出一個數字,這個數字是n-所有勾股陣列用掉的數字個數

思路:本題就是要求在n範圍內的素勾股數,在維基百科內找到相關的資料

如果 (a, b, c) 是勾股數,它們的正整數倍數,也是勾股數,即 (na, nb, nc) 也是勾股數。若果 a, b, c 三者互質(它們的最大公因數是 1),它們就稱為素勾股數

以下的方法可用來找出勾股數。設 m > nmn 均是正整數,

a = m * m - n * n;

b = 2 * m * n;

c = m * m + n * n;

mn 是互質,而且 mn 至少有一個是偶數,計算出來的 a, b, c 就是素勾股數。(若 mn 都是奇數, a, b, c 就會全是偶數,不符合互質。)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

const int N = 1000005;
long long n;
int vis[N];

long long gcd(long long a, long long b) {
    return b == 0 ? a : gcd(b, a % b);
}

int main() {
    while (scanf("%lld", &n) != EOF) {
        int ans1 = 0, ans2 = 0;
        memset(vis, 0, sizeof(vis));
        long long m = sqrt(n + 0.5);
        long long a, b, c;
        for (long long i = 1; i <= m; i++) {
            for (long long j = i + 1; j <= m; j += 2) {
                if (gcd(j, i) == 1) {      
                    a = j * j - i * i; 
                    b = 2 * i * j; 
                    c = i * i + j * j; 
                    if (c <= n) {
                        ans1++; 
                        vis[a] = vis[b] = vis[c] = 1; 
                    }
                    for (int k = 2; c * k <= n; k++)
                        vis [k * a] = vis[k * b] = vis[k * c] = 1;
                } 
            }
        }
        for (int i = 1; i <= n; i++)
            if (vis[i])
                ans2++;
        printf("%d %d\n", ans1++, n - ans2++);
    }
    return 0;
}