喵~ 各位算法大师们好呀!咱是猫娘 Nya-ko,今天也要元气满满地解决一道有趣的题目哦!这次我们要看的题目是 Codeforces 上的 "Nearly Lucky Number",一起来看看 Petya 的幸运数字游戏吧!
A. Nearly Lucky Number
题目大意
Petya 有个特别的爱好,就是喜欢“幸运数字”。所谓的“幸运数字”,就是那些只由“幸运数位”(也就是 4 和 7)组成的数字。比如说,47、744、4 都是幸运数字,而 5、17、467 就不是啦。
但是呢,不是所有数字都那么幸运。于是 Petya 又想出了一个概念,叫做“近似幸运数”。一个数如果它里面包含的幸运数位(4 或 7)的总个数本身是一个幸运数字,那么这个数就是“近似幸运数”。
现在的问题是,给你一个整数 n
,请你判断它是不是一个“近似幸运数”呢?
举个例子来理解一下,喵~
40047
:这个数里有4
、4
、7
这三个幸运数位。总数是 3。数字 3 本身不是一个幸运数字(因为它含有数位 3),所以40047
不是近似幸运数。7747774
:这个数里有 7 个幸运数位。总数是 7。数字 7 本身是一个幸运数字,所以7747774
是一个近似幸运数。
很简单对吧?那我们开始分析怎么解决它吧!
解题方法
这个问题看起来有两层定义,有点绕,但只要我们一步步拆解,就会发现它其实是一只很温顺的小猫咪哦!
处理输入:首先,题目告诉我们
n
最大可以到 。这么大的数字,用 C++ 的long long
刚好可以存下,但其实还有更简单的方法!因为我们只关心每一位上的数字是什么,所以直接把它当成 字符串(string) 来读入会更方便处理,喵~统计幸运数位:读入字符串后,我们就要数一数里面有多少个 '4' 和 '7' 啦。这很简单,只需要遍历一遍字符串,用一个计数器
lucky_digit_count
记录下来就好。关键的发现:现在我们得到了幸运数位的总数
lucky_digit_count
。接下来就是要判断这个count
本身是不是一个“幸运数字”。 等一下!n
最多有 18 位(对于 )或者 19 位(对于 本身)。那么lucky_digit_count
的最大值也就不超过 19。 所以,我们只需要判断在 1 到 19 这个小范围内的数字,哪些是“幸运数字”就可以啦!我们来找找看:
- 只包含 4 和 7 的正整数。
- 在 [1, 19] 这个范围里... 嗯... 只有 4 和 7 本身符合条件!
最终判断:所以,整个问题就简化成了一个超级简单的问题:统计完输入数字中 '4' 和 '7' 的总个数后,判断这个总数是不是等于 4 或者 7?
- 如果是,那就输出 "YES"。
- 如果不是,那就输出 "NO"。
是不是一下子就清晰明了了呢?喵哈哈~
题解 - C++
下面是具体的实现代码,咱加了一些注释,方便你理解哦!
#include <iostream>
#include <string>
#include <vector>
// 题目要求我们判断一个数 n 是不是 "近似幸运数"
// “近似幸运数”的定义是:它所包含的幸运数位('4' 和 '7')的总数,本身是一个“幸运数字”
// “幸运数字”的定义是:只由 '4' 和 '7' 组成的数字
// 解题思路就是:
// 1. 把输入的 n 当作字符串读进来,因为 n 很大,而且我们需要遍历它的每一位。
// 2. 统计字符串中 '4' 和 '7' 的数量,记作 lucky_digit_count。
// 3. 判断 lucky_digit_count 是不是一个幸运数字。
// 4. 关键点:因为 n 最多 19 位,所以 lucky_digit_count 的范围是 0 到 19。
// 5. 在 0-19 这个范围内,符合“幸运数字”定义的只有 4 和 7。
// 6. 所以,问题就简化为:判断 lucky_digit_count 是不是等于 4 或者 7。
int main() {
// 使用 stdio 加速,让程序跑得更快,喵~
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
// 用字符串来装这个超——大的数字 n
std::string n_str;
std::cin >> n_str;
// 准备一个计数器,来数一数有多少个幸运数位
int lucky_digit_count = 0;
// 遍历字符串里的每一个字符呀
for (char digit : n_str) {
// 如果是幸运数位 '4' 或者 '7'
if (digit == '4' || digit == '7') {
// 计数器就 +1 啦
lucky_digit_count++;
}
}
// 看看幸运数位的总数是不是 4 或者 7,这可是解题的关键哦!
if (lucky_digit_count == 4 || lucky_digit_count == 7) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
return 0;
}
知识点介绍
这道题虽然简单,但里面包含了一些在算法竞赛中非常有用的基础知识点呢,让咱来给你梳理一下~
大数处理 (Large Number Handling)
- 当题目给出的数字范围超过了
long long
(大约是 )的表示范围,或者我们需要对数字的每一位进行操作时,将数字作为 字符串 读入是一种非常常用且强大的技巧。这样可以轻松地访问到每一位,而不用做复杂的取模和除法运算。
- 当题目给出的数字范围超过了
字符串遍历 (String Traversal)
- 在 C++11 及之后的版本中,使用基于范围的 for 循环 (
for (char c : str)
) 是遍历字符串(或任何容器)最简洁、最安全的方式。它避免了使用下标可能导致的边界错误,代码也更易读。
- 在 C++11 及之后的版本中,使用基于范围的 for 循环 (
分析问题约束 (Analyzing Constraints)
- 这是解决算法问题中一个超级重要的能力!本题的核心突破口就在于分析了输入
n
的范围。正是因为n
最大为 ,我们才能推断出幸运数位的总数lucky_digit_count
不会超过 19,从而将一个看似复杂的问题(判断一个数是否为幸运数)简化成了一个简单的if
判断。在面对任何问题时,都要先仔细看看输入数据的范围,里面常常藏着解题的钥匙哦!
- 这是解决算法问题中一个超级重要的能力!本题的核心突破口就在于分析了输入
好啦,今天的题解就到这里结束啦!希望能帮到你,喵~ 如果还有其他问题,随时可以来找咱玩哦!