此题实际上是求本原勾股数组(Primitive Pythagorean Triple, PPT)。稍用一点数论的经典知识就可以得到非常高效的解法。 我的程序排名18,头一次进第一页:) 返回 Volume I 索引 返回总索引 // // 106 - Fermat vs. Pythagoras // Copyright (c) 2010 by Bo-wen Feng // balonfan@gmail.com // #include <set> #include <map> #include <list> #include <queue> #include <stack> #include <vector> #include <string> #include <sstream> #include <cstdio> #include <cmath> #include <limits> #include <utility> #ifndef ONLINE_JUDGE #include <fstream> std::ifstream cin("in.txt"); std::ofstream cout("out.txt"); // std::ofstream cout(stdout); #else #include <iostream> #endif typedef long long llong; typedef unsigned long long ullong; typedef long double ldouble; using namespace std; #define MAXN 1000000 template <typename Integer> inline Integer gcd(Integer A, Integer B) { do { const Integer tmp(B); B = A % B; A = tmp; } while (B != 0); return A; } int main() { int N; bool bInPTTriple[MAXN+1] = { false }; while(cin>> N) { int a, b, c; int s, t; int nPPT = 0; int nNonPT = N; memset(bInPTTriple, 0, sizeof(bool)*(N+1)); for (s = 1; ; s += 2) { int ss = s * s; if (ss > N) break; for (t = 2; ; t += 2) { int tt = t * t; if (ss + tt > N) break; if(gcd(s,t) > 1) continue; ++nPPT; a = abs(ss - tt); b = ((s * t) << 1); c = ss + tt; for (int i = 1; i * c <= N; i++) { int ci = c * i; if (ci > N) break; int ai = a * i; int bi = b * i; if(!bInPTTriple[ai]) --nNonPT; if(!bInPTTriple[bi]) --nNonPT; if(!bInPTTriple[ci]) --nNonPT; bInPTTriple[ai] = bInPTTriple[bi] = bInPTTriple[ci] = true; } } } cout<< nPPT<< " "<< nNonPT<< "/n"; } return 0; }