SDUT 1149 勾股定理第一弹 勾股数

http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=1493&cid=1149

题意:中文......

思路:

首先对于基本勾股数来说,有这样一个特点即gcd(a,b,c) = 1; 而对于所有勾股数有gcd(a,b) = gcd(b,c) = gcd(a,c);

存在一个构造基本勾股数的方法:

条件 :(m > n > 0) ,gcd(m,n) = 1 , m 与 n 的奇偶性不同  => a = m*m - n*n ; b = 2*n*m; c = m*m + n*n;   a.b,c不确定到底谁最大。

根据题意我们知道,a + b + c = s; => m*(m + n)*d = s;(d表示基本勾股数的多少倍,来求出所有的勾股数)。 令 k = (m + n), k一定是奇数。

我们首先枚举m  m < ceil(sqrt(s) - 1  , 得到m后,由于   k < 2*m(n < m) ,k < (m + n)*d里面最大的奇数。然后再枚举k,  m,k都知道了,那么结果也就知道了,

我们取C最大的哪个就可以了。

#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#include <cmath>  
#include <queue>  
#include <stack>  
#include <set>  
#include <map>  
#include <string>  
  
#define CL(a,num) memset((a),(num),sizeof(a))  
#define iabs(x)  ((x) > 0 ? (x) : -(x))  
  
#define maxn 50004  
#define ll long long  
#define inf 0x7f7f7f7f  
#define MOD 100000007  
#define lc l,m,rt<<1  
#define rc m + 1,r,rt<<1|1  
using namespace std;  
  
int gcd(int x,int y)  
{  
    if (x < y) swap(x,y);  
    if (y == 0) return x;  
    return gcd(y,x%y);  
}  
int main()  
{  
//    freopen("din.txt","r",stdin);  
//    freopen("dou.txt","w",stdout);  
    int a,b,c,d;  
    int s,k;  
    int m,n,t;  
    ll ans;  
    while (~scanf("%d",&s))  
    {  
        if (!s) break;  
        t = 0; ans = 0;  
        int top = ceil(sqrt(s/2.0)) - 1;  
        for (m = 2; m <= top; ++m)  //枚举m 
        {  
            if (s % m == 0)  //m是s的因子
            {  
                //sm存(m + n)*d的最大奇因子
                int sm = s/m;  
                while (sm % 2 == 0) sm /= 2;  
                if (m&1) k = m + 2;  
                else k = m + 1;  
                //枚举k
                for (; k < 2*m && k <= sm; k += 2)  
                {  
  
                    if (sm%k == 0 && gcd(k - m,m) == 1 && ((m^(k - m))&1) == 1)  
                    {  
  
                        d = s / (k * m * 2);  
//                        printf("%d %d %d %d\n",m,k - m,k,sm);  
                        n = k - m;  
                        if (n > m) swap(n,m);  
                        a = d*(m*m - n*n);  
                        b = 2*d*(m*n);  
                        c = d*(m*m + n*n);  
//                        printf("%d %d %d %lld\n",a,b,c,(ll)a*b*c);  
                        if (a > 0 && b > 0 && c > 0 && a + b + c == s && max(a,max(b,c)) > t)  
                        {  
                            ans = (ll)a*b*c;  
                            t = c;  
                        }  
                    }  
                }  
            }  
        }  
        cout<<ans<<endl;  
    }  
}  

  

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值