题解:洛谷 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

【核心思想】

  1. 问题分析:给定上限 \(n\),求直角边长 \(a, b \in [1, n]\) 的不同直角三角形中面积为整数的个数。面积为 \(\frac{ab}{2}\),要求为整数即 \(ab\) 为偶数。由于 \((a,b)\)\((b,a)\) 视为相同三角形,需避免重复计数。这是一个枚举 + 奇偶性判定问题,核心在于利用面积公式简化条件并控制枚举顺序去重。

  2. 算法选择

    • 有序枚举去重:令 \(b\)\(a\) 开始枚举,确保 \(a \leq b\),避免 \((a,b)\)\((b,a)\) 重复
    • 奇偶性判定\(ab \bmod 2 = 0\) 时面积为整数
  3. 关键步骤

    • 读入数据:读取 \(n\)
    • 有序枚举\(a\)\(1\)\(n\)\(b\)\(a\)\(n\)):
      • \(a \times b \bmod 2 = 0\)\(cnt \leftarrow cnt + 1\)
    • 输出结果\(cnt\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n^2)\),枚举所有满足 \(1 \leq a \leq b \leq n\) 的数对
    • 空间复杂度:\(O(1)\),仅使用计数器
  5. 枚举去重与奇偶性分析的核心思想

    • 面积整数条件转化\(\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
posted @ 2026-07-17 13:48  团爸讲算法  阅读(11)  评论(0)    收藏  举报