毕达哥拉斯三元组:若正整数x,y,z满足下x^2+y^2=z^2.满足这个方程的正整数三元组被称为毕达哥拉斯三元组。
本原毕达哥拉斯三元组:若gcd(x,y,a)=1,则正整数三元组被称为本原毕达哥拉斯三元组。
定理:正整数x,y,z构成一个本原毕达哥拉斯三元组且y为偶数,当且仅当存在互素的正整数m,n(m>n),其中m为奇数,n为偶数,或者m为偶数,n为奇数。并且满足
x=m^2-n^2
y=2*m*n
z=m^2+n^2;
例题一:Fermat vs. Pythagoras(pku 1305)
给定一个整数n,分别求n范围内的(x,y,z<=n)本原毕达哥拉斯三元组的个数,以及n以内且毕达哥拉斯三元组不涉及的数的个数。
输入:输入数据有多组,每组数据占一行,包含一个整数n。
输出:对于每组输入,输出两个数分别代表n范围内(x,y,z<=n)本原毕达哥拉斯三元组的个数以及n以内且毕达哥拉斯三元组不涉及的个数。
Sample Input
10 25 100
Sample Output
1 4 4 9 16 27
分析:根据定理,本原毕达哥拉斯三元组满足
x=m^2-n^2
y=2mn
z=m^2+n^2
其中:m>n,且m为奇数,n为偶数,或者m为偶数,n为奇数。
那么所给范围内本原毕达哥拉斯三元组数,只需对m,n进行枚举即可。然后将三元组乘以i (保证i*z在所给的范围之内),就可以求出所有的毕达哥拉斯三元组。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define N 1000010
using namespace std;
bool flag[N];///如果涉及毕达哥拉斯三元组,为1,否则为0;
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
void solve(int t)
{
int i;
int x,y,z;
int temp,m,n;
int ans1=0,ans2=0;///ans1记录本原毕达哥拉斯三元组的组数,ans2记录不涉及数的个数
memset(flag,0,sizeof(flag));///初始化
temp=sqrt(t+0.0);///m,n的最大取值为根号t
for(n=1;n<=temp;n++)
{
for(m=n+1;m<=temp;m++)
{
if(m*m+n*n>t)
break;
if(n%2!=m%2)
{
if(gcd(m,n)==1)///判断是否互素
{
x=m*m-n*n;
y=2*m*n;
z=m*m+n*n;
ans1++;
for(i=1;;i++)
{
if(i*z>t)
break;
flag[i*x]=1;
flag[i*y]=1;
flag[i*z]=1;
}
}
}
}
}
for(i=1;i<=t;i++)
if(flag[i]==0)
ans2++;
cout<<ans1<<" "<<ans2<<endl;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
solve(n);
}
return 0;
}
例题二:Right-angled Triangle(fzu 1669)
求满足以a,b为直角边,c为斜边,且满足a+b+c<=L的直角三角形的个数。输入:输入数据有多组,每组占一行,包含一个整数L(L<=2 000 000).
输出:每组输出一个正数即满足已知条件的直角三角形的个数
Sample Input
12 40
Sample Output
分析:根据定理,本原毕达哥拉斯三元组满足
1 5
x=m^2-n^2
y=2mn
z=m^2+n^2
其中:m>n,且m为奇数,n为偶数,或者m为偶数,n为奇数。
那么所给范围内本原毕达哥拉斯三元组数,只需对m,n进行枚举即可。然后将三元组乘以i(保证 i*(x+y+z)在所给的范围之内)倍,就可以求出所有满足条件的毕达哥拉斯三元组。#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define N 1000005
using namespace std;
bool flag[N];
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
void solve(int t)
{
int temp;
int m,n;
int x,y,z;
int i,ans=0;///记录本原毕达哥拉斯三元组的个数,初始化为0
memset(flag,0,sizeof(flag));///数组没啥卵用
temp=sqrt(t+0.0);
for(n=1;n<=temp;n++)
{
for(m=n+1;m<=temp;m++)
{
if(2*m*m+2*m*n>t)///x+y+z=2m^2+2mn
break;
if(n%2!=m%2)
{
if(gcd(m,n)==1)
{
x=m*m-n*n;
y=2*m*n;
z=m*m+n*n;
for(i=1;;i++)
{
if(i*(x+y+z)>t)
break;
ans++;
}
}
}
}
}
cout<<ans<<endl;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
solve(n);
}
return 0;
}