《数三角形的秘密》
📖 一、故事背景:三角形王国 🏰
1、在三角形王国里,有一种特别的三角形,叫做:
直角三角形
2、它有:
两条直角边(互相垂直 📐)
一条斜边
3、国王提出了一个问题:
👉 如果两条直角边的长度都是不超过 N 的正整数
👉有多少个直角三角形,它们的面积是整数?
4、我们的任务:
🎯帮国王数清楚,一共有多少个这样的三角形!
🧠 二、先别急写代码,先想清楚!
1️⃣ 面积公式(先搞清楚)
2️⃣ 什么时候面积是“整数”?
(1)面积是整数 ⇔
a × b 是 偶数(2)📌 因为:
偶数 ÷ 2 = 整数
奇数 ÷ 2 = 0.5(不是整数)
🧩 三、把问题拆成“小任务”
1、🎯 总目标
数一数有多少组(a, b),满足:
a、b 是正整数
a ≤ N
b ≤ N
面积是整数
2、⚠️ 重要规则
题目说:
两个三角形
(a, b)和(b, a)是同一个
也就是说:
👉3 和 4
👉4 和 3
只能算一次❗
3、✅ 解决办法
我们规定:
b 从 a 开始枚举这样就不会重复数。
🧮 四、用小例子先算一遍
🌟 假设 N = 3
所有可能的(a, b):
| a | b | a×b | 面积 | 合格? |
|---|---|---|---|---|
| 1 | 1 | 1 | 0.5 | ❌ |
| 1 | 2 | 2 | 1 | ✅ |
| 1 | 3 | 3 | 1.5 | ❌ |
| 2 | 2 | 4 | 2 | ✅ |
| 2 | 3 | 6 | 3 | ✅ |
| 3 | 3 | 9 | 4.5 | ❌ |
👉 一共3 个
🧠 五、把思路翻译成“程序语言”
采用枚举算法:
用两层 for 循环枚举直角边
如果a * b是偶数,就计数加 1
💻 六、参考程序
#include <iostream> using namespace std; int main() { int N; cin >> N; int cnt = 0; // 用来数三角形的数量 // 枚举第一条直角边 for (int a = 1; a <= N; a++) { // 枚举第二条直角边(从 a 开始,避免重复) for (int b = a; b <= N; b++) { // 判断面积是否为整数 if ((a * b) % 2 == 0) { cnt++; } } } cout << cnt << endl; return 0; }🧩 七、关键代码逐句讲解
🔹 1. 为什么b = a开始?
for (int b = a; b <= N; b++)👉 防止(3,4)和(4,3)重复计算
👉这是得分的关键细节!
🔹 2. 为什么只判断(a * b) % 2 == 0?
if ((a * b) % 2 == 0)因为:
偶数 ÷ 2 = 整数
面积就一定是整数
不用真的去算面积,省时间、省麻烦!
🎯 八、考试常见扣分点
❌ 错误 1:内循环,写成b = 1,从1开始,有重复
→ 会重复算
❌ 错误 2:判断面积为整数, 判断条件写成赋值“=”!
(a * b) % 2 = 0,
→ 会出错
❌ 错误 3:cnt 忘记 赋初值为 0,cnt++结果就会错!
🧩九、附:枚举算法通用模版:
🟡 模板 1:从 1 数到 N(最基础)
1、🎒 小故事
老师要点名,从 1 号到 N 号,一个都不漏。
2、💻 模板代码
for (int i = 1; i <= N; i++) { // 用 i 做事情 }3、🌟 常见用途
数数
累加
判断奇偶
🟡 模板 2:区间枚举(L 到 R)
1、🎒 小故事
从第 L 本书,看到第 R 本书。
2、💻 模板代码
for (int i = L; i <= R; i++) { // 检查 i }🟡 模板 3:双重枚举(两层 for)
1、🎒 小故事
每一对都试试
2、💻 模板代码
for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { // (i, j) 是一组情况 } }3、🌟 典型用途
表格
两个数的组合
二维问题
🟡 模板 4:防止重复的双枚举(非常重要 ⭐)
1、🎒 小故事
选两个人握手,A 和 B、B 和 A 是同一次
2、💻 模板代码
for (int i = 1; i <= N; i++) { for (int j = i; j <= N; j++) { // (i, j) 不重复 } }3、🌟 考试常见
本题三角形判断
配对问题
🟡 模板 5:带条件的枚举(if 判断)
1、🎒 小故事
只数“戴帽子的小朋友” 🎩
2、💻 模板代码
for (int i = 1; i <= N; i++) { if (条件) { // 满足条件才做事 } }3、🌟 例子
if (i % 3 == 0)🟡 模板 6:枚举 + 计数器(考试最爱)
1、🎒 小故事
看到一个符合要求的,就在本子上打 ✔
2、💻 模板代码
int cnt = 0; for (int i = 1; i <= N; i++) { if (条件) { cnt++; } }🟡 模板 7:枚举 2 的幂
1、🎒 小故事
数字会“翻倍生长” 🌱
2、💻 模板代码
for (int x = 1; x <= N; x *= 2) { // x = 1, 2, 4, 8, ... }🟡 模板 8:枚举数组(数组索引)
1、🎒 小故事
检查一排盒子里的东西 📦
2、💻 模板代码
for (int i = 0; i < n; i++) { // a[i] }🟡 模板 9:枚举字符串中的字符
1、🎒 小故事
一个字母一个字母读 📖
2、💻 模板代码
for (int i = 0; i < s.length(); i++) { char c = s[i]; }🟡 模板 10:枚举二维数组(二维数组索引)
1、🎒 小故事
走棋盘 ♟️
2、💻 模板代码
for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { // a[i][j] } }🧠 枚举算法“必背三句话”
📌
1️⃣ 枚举 = 不偷懒,一个一个来
2️⃣ for 写对范围,成功一半
3️⃣ 重复问题 → 第二层从 i 开始
🎯 GESP考试“万能枚举套路”
读题 ↓ 想清楚:枚举什么? ↓ for 循环写出来 ↓ if 判断条件 ↓ cnt++ ↓ 输出