勾股数(毕达哥拉斯三元组)

勾股数(毕达哥拉斯三元组)

勾股数:可以构成一组直角三角形边长的三个正整数
eg: 3 4 5
勾股数的规律:
1)任何大于1的正奇数a=2k+1,其平方t=a^2仍为奇数,且将平方数拆成两个相邻的整数 b = t / 2, c = t / 2 + 1,a,b,c为一组勾股数。
eg: 3 4 5 5 12 13 7 24 25
证明:
在这里插入图片描述

2)任意大于2的正偶数a=2*k,b = k^2-1,c = k^2+1,a,b,c为一组勾股数.
eg:4 3 5 6 8 10 8 15 17
证明:同1)a^2 + b^2 = c^2 代入k即可.
3)毕达哥拉斯三元组
不定方程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=m2-n2,y=2mn, z=m2+n2。
4)由1)可知直角三角形短直角边为大于1的奇数,另一条直角边与斜边是两个连续自然数。
5)再由4)可推导如果短直角边为奇数,则直角三角形的周长等于短直角边的平方与其本身的和

例题:
codeforce 368
题意: 给出一个正整数n问是否能够找到另外两个正整数,使得这三个正整数为一组勾股数。可以输出另外两个数字,否则输出-1.
解题思路:性质1,2。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    ll n;
    while(cin>>n){
        if(n==1||n==2){
            puts("-1");
            continue;
        }
        if(n&1){
            cout<<n*n/2<<' '<<n*n/2+1<<endl;
            continue;
        }
        else{
            n /= 2;
            cout<<n*n-1<<' '<<n*n+1<<endl;
            continue;
        }
    }
    return 0;
}

HDU 6411 Find Integer
题意:
给出n,a 求不定方程a^n + b^n = c^n 的一组解b,c.(其中b,c>1)
解题:
1)n=0,显然无解
2)n=1,最简单b=a,c=2*a
3)n=2,勾股数同上一题.
4)n>2,费马大定理x^n + y^n = z^n 在(n>2情况下)无解 直接-1

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int T;
    ll n,a;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&a);
        if(n==0||n>2){
            puts("-1 -1");
            continue;
        }
        if(n==1){
            printf("%lld %lld\n",a,a<<1);
            continue;
        }
        else{
            if(a&1){
                printf("%lld %lld\n",a*a/2,a*a/2+1);
            }
            else{
                a /= 2;
                printf("%lld %lld\n",a*a-1,a*a+1);
            }
        }
    }
    return 0;
}

POJ 1305 Fermat vs. Pythagoras
题意:给出正整数n,求出(x,y,z<=n)满足不定方程 x^2 + y^2 = z^2且gcd(x,y,z)==1的三元组(x,y,z)的个数,同时求出n以内且毕达哥拉斯三元组不涉及的数的个数。
思路:利用性质3,枚举m,n即可。
AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1e6+10;
bool vis[maxn];
int gcd(int a,int b){
    return (b==0)?a:gcd(b,a%b);
}
template <typename T>
inline T Max(const T &a,const T &b){
    return a>b?a:b;
}
template <typename T>
inline T Min(const T &a,const T &b){
    return a<b?a:b;
}
int main(){
    int n,up;
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;++i){
            vis[i] = 0;
        }
        up = (int)sqrt(1.0*n+0.5);
        int ans1=0,ans2=0;
        //i,j奇偶性一定不同
        for(int i=1;i<=up;i+=2){//枚举奇数
            for(int j=2;j<=up;j+=2){//枚举偶数
                int d = gcd(i,j);
                if(d==1){
                    int a = Max(i,j);
                    int b = Min(i,j);
                    int x = a*a-b*b;
                    int y = 2*a*b;
                    int z = a*a+b*b;
                    if(z<=n){
                        ++ans1;
                    }
                    else{
                        continue;
                    }
                    for(int k=1;k*z<=n;++k){
                        vis[x*k] = 1;
                        vis[y*k] = 1;
                        vis[z*k] = 1;
                    }
                }
            }
        }
        for(int i=1;i<=n;++i){
            if(!vis[i]) ++ans2;
        }
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值