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; }