题解:洛谷 B4356 数三角形
【题目来源】
洛谷:B4356 [GESP202506 二级] 数三角形 - 洛谷
【题目描述】
直角三角形有两条直角边与一条斜边,设两条直角边的长度分别为 \(a,b\),则直角三角形的面积为 \(\frac{ab}{2}\)。
请你计算当直角边长 \(a,b\) 均取不超过 \(n\) 的正整数时,有多少个不同的面积为整数的直角三角形。直角边长分别为 \(a,b\) 和 \(a',b'\) 的两个直角三角形相同,当且仅当 \(a=a', b=b'\) 或者 \(a=b', b=a'\)。
【输入】
一行,一个整数 \(n\),表示直角边长的最大值。
【输出】
输出一行,一个整数,表示不同的直角三角形数量。
【输入样例】
3
【输出样例】
3
【核心思想】
-
问题分析:给定上限 \(n\),求直角边长 \(a, b \in [1, n]\) 的不同直角三角形中面积为整数的个数。面积为 \(\frac{ab}{2}\),要求为整数即 \(ab\) 为偶数。由于 \((a,b)\) 和 \((b,a)\) 视为相同三角形,需避免重复计数。这是一个枚举 + 奇偶性判定问题,核心在于利用面积公式简化条件并控制枚举顺序去重。
-
算法选择:
- 有序枚举去重:令 \(b\) 从 \(a\) 开始枚举,确保 \(a \leq b\),避免 \((a,b)\) 和 \((b,a)\) 重复
- 奇偶性判定:\(ab \bmod 2 = 0\) 时面积为整数
-
关键步骤:
- 读入数据:读取 \(n\)
- 有序枚举(\(a\) 从 \(1\) 到 \(n\),\(b\) 从 \(a\) 到 \(n\)):
- 若 \(a \times b \bmod 2 = 0\):\(cnt \leftarrow cnt + 1\)
- 输出结果:\(cnt\)
-
时间/空间复杂度:
- 时间复杂度:\(O(n^2)\),枚举所有满足 \(1 \leq a \leq b \leq n\) 的数对
- 空间复杂度:\(O(1)\),仅使用计数器
-
枚举去重与奇偶性分析的核心思想:
- 面积整数条件转化:\(\frac{ab}{2} \in \mathbb{Z} \Leftrightarrow ab \equiv 0 \pmod{2}\),即 \(a\) 和 \(b\) 中至少有一个为偶数,将几何问题转化为数论问题
- 有序枚举去重:通过约束 \(a \leq b\),每个无序对 \(\{a,b\}\) 只被计数一次,避免 \((2,3)\) 和 \((3,2)\) 的重复。若使用 \(b\) 从 \(1\) 到 \(n\) 枚举,会导致重复计数
- 乘法奇偶性:两数乘积为偶数当且仅当至少一数为偶数,因此只需检查 \(ab \bmod 2\) 即可,无需分别判断 \(a\) 和 \(b\) 的奇偶性
- 适用于组合计数、有序枚举去重类基础问题
【算法标签】
入门 #语法基础
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n; // 输入的上限值
int cnt = 0; // 计数器,统计满足条件的数对个数
cin >> n; // 输入正整数n
// 外层循环:遍历所有可能的a值(1到n)
for (int a = 1; a <= n; a++)
{
// 内层循环:遍历所有可能的b值(a到n)
for (int b = a; b <= n; b++)
{
// 检查a和b的乘积是否为偶数
if (a * b % 2 == 0)
cnt++; // 满足条件则计数器加1
}
}
// 输出满足条件的数对总数
cout << cnt << endl;
return 0;
}
【运行结果】
3
3
浙公网安备 33010602011771号