这里给出勾股数公式:
直角三角形三条边a, b, c,其中a,b是直角边。
则 a=2*m*n
b=m^2-n^2
c=m^2+n^2
当然,这是有前提条件的,也就是其局限性:“勾股数的公式还是有局限的。勾股数公式可以得到所有的基本勾股数,但是不可能得到所有的派生勾股数。比如6,8,10;9,12,15…,就不能全部有公式计算出来”
也就是说,3,4,5可以求出来,但是其倍数6,8,10就不行了。
这里要注意几个问题:
1.构成三角形的条件:
2*m*n+m^2-n^2 > m^2+n^2
既m>n
2.a, b, c互质,即无法得到派生的勾股数。
Poj1305求勾股数出现的次数
题意:给出一个数n求出1-n中勾股数的个数,其中如果是倍数算一次,例如3 4 5,6 8 10 算一组。
输出组数和1,n中没有在勾股数中出现过的数字
其中有一句是看了discuss才理解的
You are also to compute the number of values 0 < p <= N such that p is not part of any triple (not just relatively prime triples
意思是
对于方程x^2 + y^2 = z^2有解(triples)为(x,y,z),p = |{k|k!=x && k!=y && k!=z for any(x,y,z) that fits x^2 + y^2 = z^2, k <= N, k为正整数}|
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string.h>
#define M 1000000
using namespace std;
bool flag[1000005];
__int64 gcd(__int64 a,__int64 b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
int main()
{
__int64 n,s,t,a,b,c,ans1,ans2,i;
while(scanf("%I64d",&n)!=EOF)
{
ans1=0,ans2=0;
memset(flag,0,sizeof(flag));
for(t=1;t<=n;t++)
{
for(s=t+1; 2*s*s+2*s*t<=M; ++s)
{
a=2*s*t;
b=(s*s-t*t);
c=(s*s+t*t);
if(c>n)
break;
if(gcd(gcd(a,b),c)!=1)
continue;
ans1++;
for(i=1;c*i<=n;i++)
{
flag[i*a]=true;
flag[i*b]=true;
flag[i*c]=true;
}
}
}
for(i=1;i<=n;i++)
if(!flag[i])
ans2++;
printf("%I64d %I64d\n",ans1,ans2);
}
return 0;
}