poj1305 Fermat vs. Pythagoras(勾股数)
题意:
设不定方程:x^2+y^2=z^2
若正整数三元组(x,y,z)满足上述方程,则称为毕达哥拉斯三元组。
若gcd(x,y,z)=1,则称为本原的毕达哥拉斯三元组。
定理:
正整数x,y,z构成一个本原的毕达哥拉斯三元组且y为偶数,当且仅当存在互素的正整数m,n(m>n),其中m,n的奇偶性不同,
并且满足
x=m^2-n^2,y=2*m*n, z=m^2+n^2
本题目让你求的是,在n范围内(x,y,z<=n)本原的毕达哥拉斯三元组的个数,以及n以内且毕达哥拉斯三元组不涉及的数的个数
思路:
本原的三元组有:(3,4,5),(7,24,25),(5,12,13),(8,15,17),即第一个要输出的为4
所有的毕达哥拉斯三元组,除了上述4个外,还有:(6,8,10),(9,12,15),(12,16,20),(15,20,25)
不包含在这些三元组里面的<=n的数有9个。
思路:很显然,依据前面给出的定理,只要枚举一下m,n(m,n<=sqrt(n)),然后将三元组乘以i(保证i*z在范围内即可),
就可以求出所有的毕达哥拉斯三元组。
代码:
/*100内的勾股数有52 勾股数满足: x=a*a-b*b; y=2*a*b; z=a*a+b*b; 其中a,b的奇偶一定要不同 */ #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 1000005 int vis[N]; int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); } int main() { int n; while(~scanf("%d",&n)) { memset(vis,0,sizeof(vis)); int x,y,z; int a,b,c; int ans=0;int tot=0; for(int i=1;i*i<=n;i+=2) { for(int j=2;j*j<=n;j+=2) { a=max(i,j); b=min(i,j); c=gcd(i,j); if(c==1) { x=a*a-b*b; y=2*a*b; z=a*a+b*b; for(int k=1;k*z<=n;k++) { vis[x*k]=1; vis[y*k]=1; vis[z*k]=1;//cout<<x*k<<" "<<y*k<<" "<<z*k<<endl;tot++; } if(z<=n) { ans++; } } } } int cnt=0; for(int i=1;i<=n;i++) if(!vis[i]) cnt++; printf("%d %d\n",ans,cnt);//cout<<tot<<endl; } }