如何统计指定范围内整数直角三角形数量并输出其周长?
解决整数直角三角形周长统计问题
首先,咱们先梳理下你现有代码里的几个关键问题:
- 循环条件错误:第三层循环里
for ( c = b; b <= Q; ++c),终止条件应该是c <= Q而不是b <= Q,不然c会无限制递增,要么死循环要么完全不符合预期。 - 精度陷阱:用
pow()计算平方会引入浮点数精度误差,比如pow(2,2)可能会得到3.9999999999,和整数比较时直接出错,改用整数乘法a*a就能避免这个问题。 - 统计逻辑偏差:你现在是每找到一个三元组就累加计数器并输出,但示例要求的是按周长分组统计每个周长对应的直角三角形数量(比如周长168对应3个不同三角形),而不是累计计数。
- 范围冗余:a的范围可以优化,因为
a + b + c >= a + a + a = 3a,所以a最大只能是Q/3,超过这个值的话三个数的和肯定大于Q,没必要做无用遍历。
修正后的核心思路
- 用一个数组(因为周长范围固定在P到Q)记录每个周长对应的三角形数量,初始化所有值为0。
- 正确遍历a、b、c的范围,避免重复统计:
- a从1开始到
Q/3(保证三个数的和不超过Q) - b从a开始(避免(3,4,5)和(4,3,5)被算作两个不同三角形)
- 通过
a² + b² = c²推导c,验证c是否为整数,同时确保周长s = a+b+c在P到Q之间,且c > b(保证a<=b<c的顺序,彻底去重)。
- a从1开始到
- 遍历完所有三元组后,从P到Q逐个检查每个周长的计数,输出符合要求的周长和对应数量。
修正后的代码
#include <iostream> #include <cmath> using namespace std; int main() { int P, Q; cin >> P >> Q; // 数组索引对应周长值,存储该周长的直角三角形数量 int count[Q + 1] = {0}; for (int a = 1; a <= Q / 3; ++a) { for (int b = a; ; ++b) { // 用long long避免整数溢出 long long a_sq = (long long)a * a; long long b_sq = (long long)b * b; long long c_sq = a_sq + b_sq; int c = sqrt(c_sq); int s = a + b + c; // 周长超过Q就停止增大b,没必要继续循环 if (s > Q) { break; } // 验证c是否为整数,且满足a<=b<c的顺序 if ((long long)c * c == c_sq && c > b) { if (s >= P && s <= Q) { count[s]++; } } } } // 按要求输出结果:遍历P到Q,输出有三角形的周长和对应数量 for (int s = P; s <= Q; ++s) { if (count[s] > 0) { cout << s << " " << count[s] << " "; } } cout << endl; return 0; }
关键细节说明
- 整数溢出处理:用
long long存储平方值,避免a、b较大时,a*a超过int的取值范围导致溢出。 - 循环终止优化:当b增大到周长超过Q时,直接break内层循环,减少不必要的计算。
- 去重逻辑:通过
a <= b < c的限制,确保每个直角三角形只被统计一次,不会重复计数。
测试输入154 180,输出就是156 1 160 1 168 3 176 1 180 3,完全符合示例要求。
内容的提问来源于stack exchange,提问作者eulerisgood
相关产品推荐
相关产品推荐

