P10424 [蓝桥杯 2024 省 B] 好数
题目描述
一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位......)上的数字是奇数,偶数位(十位、千位、十万位......)上的数字是偶数,我们就称之为"好数"。
给定一个正整数 N N N,请计算从 1 1 1 到 N N N 一共有多少个好数。
输入格式
一个整数 N N N。
输出格式
一个整数代表答案。
输入输出样例 #1
输入 #1
24
输出 #1
7
输入输出样例 #2
输入 #2
2024
输出 #2
150
说明/提示
样例 1 解释
24 24 24 以内的好数有 1 , 3 , 5 , 7 , 9 , 21 , 23 1,3,5,7,9,21,23 1,3,5,7,9,21,23,一共 7 7 7 个。
数据规模与约定
- 对于 10 % 10\% 10% 的测试数据, 1 ≤ N ≤ 100 1 \leq N \le 100 1≤N≤100。
- 对于全部的测试数据, 1 ≤ N ≤ 1 0 7 1 \le N \leq 10^7 1≤N≤107。
- 洛谷链接
思路讲解
首先想到的是需要高效地检查每个数字的各位数字是否符合条件。
核心思路是分离奇偶位的检查:
- 检查奇数位:直接从个位开始,每次取最后一位数字判断是否为奇数,然后通过/=100跳过两位(同时跳过下一个偶数位)
- 检查偶数位:先去掉个位(/=10),让十位变成新的个位,再用同样的方式检查并跳过两位 这种方法避免了复杂的位次计算,通过两次简洁的循环就能完成检查。对于每个数字,我们只需遍历其一半的位数,大大提升了效率。
在goodNum()方法中,用了两个错位循环来"跳位"判断:
一个从个位 开始,每次跳两位(num1 /= 100),只判断奇数位
另一个从十位开始,每次跳两位(num /= 100),只判断偶数位
java
import java.util.Scanner;
public class Main {
// 判断数字是否为偶数
public static boolean oddEven(int num) {
return num % 2 == 0;
}
// 判断一个数是否为"好数"
public static boolean goodNum(int num) {
int num1 = num;
// 检查所有奇数位(个位、百位、万位...)
while (num1 > 0) {
int digit = num1 % 10; // 取当前最低位(奇数位)
if (oddEven(digit)) { // 若奇数位是偶数 -> 不符合
return false;
}
num1 /= 100; // 移除后两位(跳到下一个奇数位)
}
// 检查所有偶数位(十位、千位...)
num /= 10; // 移除个位,使十位成为最低位
while (num > 0) {
int digit = num % 10; // 取当前最低位(偶数位)
if (!oddEven(digit)) { // 若偶数位是奇数 -> 不符合
return false;
}
num /= 100; // 移除后两位(跳到下一个偶数位)
}
return true; // 所有位均满足条件
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int count = 0;
for (int i = 1; i <= N; i++) {
if (goodNum(i)) {
count++;
}
}
sc.close();
System.out.println(count);
}
}