106

前几天听见他们做了,知道要用新知识,就直接查知识了:来自http://www.leyle.com/archives/361106

毕达哥拉斯三元组——快速生成勾股数

丢番图求毕达哥拉斯三元组的方法

设有任意两个整数,组成如下:

其积的2倍;

两个的平方差;

两者的平方和;

这样就得到了一个勾股数。

如有整数2,3

那么就有

2x3x2=12;

(3×3)-(2×2)=5

(2×2)+(3×3)=13

那么,5,12,13就是勾股数了。

毕达哥拉斯规则还有最后一个调整。计算出三个数后,可以选择我们喜欢的其他任何数来乘以这三个数。

因此,将3-4-5三条边都乘以2可以得到6-8-10这个勾股三角形。

我本来还想不对每次求出的乘以倍数计算,发现是不对的,会漏下很多情况,改后就过了

//============================================================================
// Name        : 106.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

int ans1, ans2, n, a, b, c;
bool flag[1000010];

int gcd(int x, int y){
	if(x < y) swap(x, y);
	int r;
	while(x%y){
		r = x%y;
		x = y;
		y = r;
	}
	return y;
}

int exprime(int x, int y){
	if(gcd(x, y) == 1) return 1;
	else return 0;
}

int main(){
	freopen("a.txt", "r", stdin);
	while(scanf("%d", &n)!=EOF){
		memset(flag, false, sizeof(flag));
		ans1 = 0;
		ans2 = 0;
		for(int i = 1;i <= sqrt(n);i++){
			for(int j = i+1;j <= sqrt(n);j++){
				a = i*j*2;
				b = (i*i-j*j)>0?(i*i-j*j):(j*j-i*i);
				c = i*i+j*j;
				if(a > b) swap(a, b);
				if(b > c) swap(b, c);
				if(a > b) swap(a, b);
				if(a >0&&a <= n&&b > 0&&b <= n&&c > 0&&c <= n){
					flag[a] = true;
					flag[b] = true;
					flag[c] = true;
//					printf("%d %d %d\n", a, b, c);
					if(exprime(a, b)&&exprime(b, c)&&exprime(a, c)){
						ans1++;
						for(int k = 2;k*c <= n;k++){
							flag[a*k] = true;
							flag[b*k] = true;
							flag[c*k] = true;
						}
					}
				}
			}
		}
		for(int i = 1;i <= n;i++){
			if(flag[i] == false) ans2++;
		}
		printf("%d %d\n", ans1, ans2);
	}
	return 0;
}

posted @ 2011-05-27 17:07  KOKO's  阅读(251)  评论(0编辑  收藏  举报