📚 算法笔记:P10424 蓝桥杯 2024 省 B 好数
1. 题目简述
P10424 [蓝桥杯 2024 省 B 好数 - 洛谷](https://www.luogu.com.cn/problem/P10424)
- 定义:从低位到高位(个位为第 1 位),奇数位上的数字是奇数,偶数位上的数字是偶数。
- 任务 :统计 1 1 1 到 N N N 之间有多少个"好数"。
- 范围 : N ≤ 10 7 N \le 10^7 N≤107。
2. 核心代码 (C++ 实现)
c++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
/**
* 判断好数的核心函数
* 参数 i: 待判断的整数
* 返回值: bool 是否为好数
*/
bool isGood(ll i)
{
int pos = 1; // 记录当前是第几位(从 1 开始)
while(i > 0)
{
int digit = i % 10; // 取当前最低位数字
if(pos % 2 != 0) // 奇数位(个、百、万...)
{
if(digit % 2 == 0) return false; // 若数字为偶数,判定失败
}
else // 偶数位(十、千、十万...)
{
if(digit % 2 != 0) return false; // 若数字为奇数,判定失败
}
i /= 10; // 丢掉已经处理完的位
pos++; // 位数向高位移动
}
return true;
}
void solve()
{
ll N = 0;
cin >> N;
ll count = 0;
// 遍历 1 到 N
for(ll i = 1; i <= N; i++)
{
// 剪枝优化:只有个位是奇数的数字才可能是好数
if(i % 2 != 0 && isGood(i))
{
count++;
}
}
cout << count << endl;
}
int main()
{
// 提高大数据量下的读写效率
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int _ = 1;
while(_--)
{
solve();
}
return 0;
}
3. 核心考点与注意事项
- 进制拆分 :这是处理数字位数的通用模板。利用
% 10取位,/ 10降位的循环是算法竞赛的必备技能。 - 复杂度控制 : N = 10 7 N=10^7 N=107 的数据量对于线性遍历 O ( N ) O(N) O(N) 来说是可以接受的。在 C++ 中,单层循环配合简单的整数运算,耗时通常在 1 秒以内。
- 位权顺序 :题目明确说明从低位到高位。如果从高位开始处理,由于不同数字的总位数不同,逻辑会变得非常臃肿。
4. 易错点回顾 (My Mistakes)
1. 进制拆分的"死循环"陷阱
- 错误经历 :在
while(i > 0)中忘记写i /= 10。- 后果:程序会死死掐住个位数不放,导致 TLE(运行超时)。
- 教训 :取位、处理、降位必须成套出现。
2. 变量更新遗漏
- 错误经历 :忘记在循环内自增
pos++。- 后果:逻辑判定始终停留在"奇数位",导致判定结果全错。