一、先看原题:



二、🌸 题目故事:什么是"优美的数字"
1、🧸题目故事化
(1)小 A 是一个数字审美家 🎨
他觉得------
一个数字如果 每一位长得都一样 ,
那它就是一个 "优美的数字" ✨
(2)🌟 举例说明
| 数字 | 是不是优美 | 原因 |
|---|---|---|
| 7 | ✅ | 只有一位 |
| 11 | ✅ | 1 和 1 一样 |
| 222 | ✅ | 全是 2 |
| 121 | ❌ | 中间不一样 |
| 2025 | ❌ | 0、2、5 都不同 |
2、🎯 题目要你做什么?
👉 输入一个正整数 n
👉 统计 1 ~ n 之间有多少个"优美的数字"
三、🧠 同学们先想一想:我们该怎么做?
1、枚举算法:
枚举范围 1~n
cpp
for (int i = 1; i <= n; i++) {
.............
}
2、判断方法:
如果给你一个数字,比如 333 ,
我们怎么判断它是不是"优美的"?
3、拆数比较:
1️⃣ 先拆出最后一位:3
2️⃣ 再拆出前面的每一位
3️⃣ 只要有一个不是 3 → ❌ 不优美
4️⃣ 全都一样 → ✅ 优美
👉 这就是本题的核心算法思想
四、🧩 算法拆解(非常关键)
我们要做三层事情:
🪜 第 1 层:从 1 数到 n
cpp
for (int i = 1; i <= n; i++)
📌 含义:
👉 每个数字都检查一遍
🪜 第 2 层:拆数字
比如:i = 777
-
最后一位:
i % 10 = 7 -
剩下的:
i / 10 = 77
👉 不断拆,直到没数字了
🪜 第 3 层:检查每一位是否一样
-
只要发现一位不一样
-
就立刻说:❌ 不优美
五、✨ 参考程序逐行讲解
✅ 完整代码
cpp
#include <algorithm>
#include <cstdio>
using namespace std;
int n, ans;
int main() {
// 输入上限 n
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int v = i % 10; // 记住最后一位
int t = i / 10; // 剩下的部分
int chk = 1; // 假设它是优美的
while (t) {
if (t % 10 != v)
chk = 0; // 发现不一样,标记为不优美
t /= 10;
}
ans += chk; // 如果是优美的,就加 1
}
printf("%d\n", ans);
return 0;
}
六、🎯 本题考点:
| 考点 | 是否重要 |
|---|---|
% 取余位 |
⭐⭐⭐⭐⭐ |
/ 去个位 |
⭐⭐⭐⭐⭐ |
| while 拆数字 | ⭐⭐⭐⭐ |
| 标记物 | ⭐⭐⭐⭐ |
| 枚举算法 | ⭐⭐⭐⭐ |
七、🌈 "记忆口诀"
🔢 数字题,不慌张
/ 除 10 去尾巴
% 模 10 看最后
🚨 比比是否相同
🎯 累加最后出答案
八、附:📘 GESP 二级|拆数字模板速查表
适用范围 :GESP C++ 二级(高频考点)
核心思想 :用% 10看最后一位,用/ 10去掉最后一位
(一)、拆数字最基础模板(必背)
int x;
cin >> x;
while (x > 0) {
int digit = x % 10; // 取最后一位
// 👉 在这里处理 digit
x /= 10; // 去掉最后一位
}
🧠 口诀 :
%10 看尾巴,/10 去尾巴,while 一直拆
(二)、判断型模板(是否满足条件)
👉 用于:优美数字 / 是否含某数 / 是否回文
int x;
cin >> x;
int ok = 1; // 先假设成立
while (x > 0) {
int digit = x % 10;
if (/* 条件不满足 */) {
ok = 0;
break;
}
x /= 10;
}
if (ok) cout << "YES";
else cout << "NO";
示例:判断"优美数字"(所有位都一样)
int x;
cin >> x;
int last = x % 10; // 标准数字
x /= 10;
int ok = 1;
while (x > 0) {
if (x % 10 != last) {
ok = 0;
break;
}
x /= 10;
}
cout << ok;
(三)、计数型模板(统计满足条件的位数)
👉 用于:统计 5 的个数 / 统计奇数位
int x;
cin >> x;
int cnt = 0;
while (x > 0) {
int digit = x % 10;
if (/* digit 满足条件 */)
cnt++;
x /= 10;
}
cout << cnt;
示例:统计数字中有几个 5
int x;
cin >> x;
int cnt = 0;
while (x > 0) {
if (x % 10 == 5)
cnt++;
x /= 10;
}
cout << cnt;
(四)、累加计算型模板(各位和 / 各位乘积)
int x;
cin >> x;
int sum = 0;
while (x > 0) {
sum += x % 10;
x /= 10;
}
cout << sum;
📌 若算乘积:把 求和 改成 求乘积,初值设为 1
(五)、反转数字模板(回文数核心)
int x;
cin >> x;
int rev = 0;
while (x > 0) {
rev = rev * 10 + x % 10;
x /= 10;
}
cout << rev;
示例:判断回文数
int x;
cin >> x;
int y = x;
int rev = 0;
while (y > 0) {
rev = rev * 10 + y % 10;
y /= 10;
}
if (rev == x)
cout << "YES";
else
cout << "NO";
(六)、枚举 + 拆数字模板(GESP 二级大题核心)
👉 用于:统计 1 ~ n 中满足条件的数字个数
int n;
cin >> n;
int ans = 0;
for (int i = 1; i <= n; i++) {
int x = i;
int ok = 1;
while (x > 0) {
int digit = x % 10;
if (/* 条件不满足 */) {
ok = 0;
break;
}
x /= 10;
}
ans += ok;
}
cout << ans;
📌 第三部分编程题第 1 题《优美的数字》= 直接套这个模板
(七)、考试速记区
🔢 数字题不慌张
% 模 10 看尾巴
/ 除 10 去尾巴
🔁 while 一直拆
🧠 根据条件去判断
👉最后一起出答案