UVA 106 Fermat vs. Pythagoras(勾股数)

题意:

给定一个整数N,你要写一个程序来计算出两个关于以下方程解的量:
x^2 + y^2 = z^2
其中x,y和Z都限定为正整数且小于等于N。你要计算出所有满足x < y < z的三元组(x,y,z)的数量,并且使得x,y和z两两互质,即没有大于1的公因数。你还要计算出所有满足下面条件的p的数量:0 < p ≤ N,且p没有在所有这样的三元组中出现(并不限定为两两互质的三元组)。

解析:

由以上定义我们推导出勾股公式:
对于a2+b2=c2,求出所有满足条件的(a,b,c)三元组,输出a,b,c三个互质的组别的数量和从1到N中所有
的三元组中都没有出现过的数字的个数。
要求互质毕达哥拉斯三元组,可直接得到:
a = m^2-n^2 b = 2mn c = m^2+n^2
因为三个变量之间两两互质,所以a,b中必为一奇一偶。
(详细证明见:http://www.cnblogs.com/devymex/archive/2010/08/07/1799713.html
因此问题的复杂度就可以降为O(m*n),即:最坏1000*1000。
除互质勾股数外,其他所有勾股数三元组都可以由求出的互质勾股数乘以一定的系数得到,由此可以得到三元组没出现的数字的个数(n - 所有勾股数个数)。

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1000001;
bool used[N];
int n;
void init() {
    for(int i = 0; i <= n; i++) {
        used[i] = false;
    }
}
int gcd(int x, int y) {
    if(y == 0) return x;
    return gcd(y, x % y);
}
void solve() {
    int limit = (int)floor(sqrt(n));
    int cnt = 0, cnt2 = 0;
    ll a, b, c;
    for(int s = 1; s <= limit; s++) {
        for(int r = s+1; r <= limit; r += 2) {
            c = r*r + s*s;
            if(gcd(r,s) == 1 && c <= n) {
                a = r*r - s*s;
                b = 2*r*s;
                cnt++;
                for(int i = 1; i * c <= n; i++) {
                    used[a*i] = used[b*i] = used[c*i] = true;
                }
            }
        }
    }
    for(int i = 1; i <= n; i++) {
        if(!used[i]) cnt2++;
    }
    printf("%d %d\n",cnt,cnt2);
}
int main() {
    while(scanf("%d", &n) != EOF) {
        init();
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值