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; } }