特殊的不定方程——毕达哥拉斯三元组(勾股数组)

毕达哥拉斯三元组:若正整数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;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值