luogu-B3850 [GESP202306 四级] 幸运数
GESP C++四级真题,函数应用练习,难度⭐⭐★☆☆。
luogu-B3850 [GESP202306 四级] 幸运数
题目要求
题目描述
小明发明了一种 “幸运数”。一个正整数,其偶数位不变(个位为第 位,十位为第 位,以此类推),奇数位做如下变换:将数字乘以 ,如果不大于 则作为变换结果,否则把结果的各位数相加,如果结果不大于 则作为变换结果,否则(结果仍大于 )继续把各位数相加,直到结果不大于 ,作为变换结果。变换结束后,把变换结果的各位数相加,如果得到的和是 的倍数,则称一开始的正整数为幸运数。
例如,:第 位为 ,乘以 结果为 ,大于 ,各位数相加为 ,仍大于 ,继续各位数相加,最后结果为 ;第 位为 ,变换结果为 ;第 位为 ,变换结果为 。最后变化结果为 ,对于结果 其各位数之和为 ,是 的倍数。因此 是幸运数。
输入格式
输入第一行为正整数 ,表示有 个待判断的正整数。约定 。
从第 行开始的 行,每行一个正整数,为待判断的正整数。约定这些正整数小于 。
输出格式
输出 行,对应 个正整数是否为幸运数,如是则输出 ‘T’,否则输出 ‘F’。
提示:不需要等到所有输入结束在依次输出,可以输入一个数就判断一个数并输出,再输入下一个数。
输入输出样例 #1
输入 #1
2
16347
76344
输出 #1
T
F
题目分析
1. 理解题目要求
这道题要求我们判断一个数是不是"幸运数"。一个数要成为幸运数需要满足以下条件:
- 对数字的奇数位(从右往左数,个位是第1位)进行特殊变换
- 偶数位保持不变
- 最后把所有数位加起来,如果是8的倍数就是幸运数
2. 关键函数实现
我们的代码主要包含三个重要的函数:
计算数位和的函数
sum_digit
- 输入一个数
- 计算公式: (其中 是 的每一位数字)
- 比如:
数字变换函数
trans_num
- 输入一个数字
- 先计算
- 如果结果大于9,就不断把各位数字相加,直到结果不大于9
- 比如:
判断幸运数的函数
is_lucky_num
- 从右往左处理每一位数字
- 奇数位用
trans_num
变换 - 偶数位保持不变
- 最后判断所有数位之和是否能被8整除
3. 代码实现方式
我们提供了两种实现方法:
数字处理方法
- 直接对数字进行运算
- 使用除法和取余来获取每一位数字
- 优点是不需要额外空间
字符串处理方法
- 把数字转成字符串
- 直接访问每一位数字
- 更容易理解和操作
两种方法都可以解决问题,选择你觉得更容易理解的方法即可。
4. 举个例子
以数字16347为例:
- 从右往左看,第1、3、5位(7、3、1)需要变换
- 7变成4,3不变,1变成7
- 变换后得到76344
- 7+6+3+4+4=24,是8的倍数
- 所以16347是幸运数
{% include custom/custom-post-content-inner.html %}
示例代码
方法一:数字处理
#include <iostream>
/**
* 计算一个数字各位数字之和
* @param num 待计算的数字
* @return 各位数字之和
*/
int sum_digit(int num) {
int sum = 0; // 存储各位数字之和
while (num != 0) {
sum += num % 10; // 取出最后一位数字并累加
num /= 10; // 去掉最后一位数字
}
return sum;
}
/**
* 对数字进行变换处理
* 将数字乘以7,如果结果大于9,则将各位数字相加直到结果不大于9
* @param num 待变换的数字
* @return 变换后的结果(保证结果不大于9)
*/
int trans_num(int num) {
int sum = num * 7; // 先将数字乘以7
while(sum > 9) { // 如果结果大于9,继续处理
sum = sum_digit(sum); // 计算各位数字之和
}
return sum;
}
/**
* 判断一个数是否为幸运数
* 幸运数的定义:将奇数位的数字进行变换后,所有位数字之和是8的倍数
* @param num 待判断的数字
* @return true表示是幸运数,false表示不是幸运数
*/
bool is_lucky_num(long long num) {
int sum = 0; // 记录所有位数字之和
int idx = 0; // 记录当前处理的是第几位
while (num != 0) {
// 取出最后一位数字
int c_num = num % 10;
// 如果是奇数位(从右往左数,从0开始),进行变换
if (idx % 2 == 0) {
c_num = trans_num(c_num);
}
sum += c_num; // 累加当前位的数字
num /= 10; // 去掉最后一位
idx++; // 位数加1
}
// 判断和是否是8的倍数
if (sum % 8 == 0) {
return true;
}
return false;
}
int main() {
int n; // 待处理的数字个数
std::cin >> n;
// 循环处理每个数字
for (int i = 0; i < n; i++) {
long long number; // 当前要判断的数字
std::cin >> number;
// 判断并输出结果
if (is_lucky_num(number)) {
std::cout << 'T' << "\n";
} else {
std::cout << 'F' << "\n";
}
}
return 0;
}
方法二: 字符串处理
#include <iostream>
#include <string>
/**
* 计算一个数字各位数字之和
* @param num 待计算的数字
* @return 各位数字之和
*/
int sum_digit(int num) {
int sum = 0; // 存储各位数字之和
while (num != 0) {
sum += num % 10; // 取出最后一位数字并累加
num /= 10; // 去掉最后一位数字
}
return sum;
}
/**
* 对数字进行变换处理
* 将数字乘以7,如果结果大于9,则将各位数字相加直到结果不大于9
* @param num 待变换的数字
* @return 变换后的结果(保证结果不大于9)
*/
int trans_num(int num) {
int sum = num * 7; // 先将数字乘以7
while(sum > 9) { // 如果结果大于9,继续处理
sum = sum_digit(sum); // 计算各位数字之和
}
return sum;
}
/**
* 判断一个数是否为幸运数
* @param num 待判断的数字
* @return true表示是幸运数,false表示不是幸运数
* 判断规则:
* 1. 将数字转换为字符串处理
* 2. 对奇数位(从右往左,从0开始)进行变换
* 3. 计算所有位数字之和
* 4. 判断和是否是8的倍数
*/
bool is_lucky_num(long long num) {
// 将数字转换为字符串便于处理
std::string num_str = std::to_string(num);
// 记录所有位数字之和
int sum = 0;
// 从右往左遍历每一位
for (int i = 0; i < num_str.length(); i++) {
// 处理奇数位(从右往左数,从0开始)
if (i % 2 == 0) {
// 将字符转换为数字
int c_num = num_str[num_str.length() -1 -i] - '0';
// 进行变换
c_num = trans_num(c_num);
// 将变换后的数字转回字符
num_str[num_str.length() -1 -i] = char(c_num + '0');
}
// 累加当前位的数字
sum += num_str[num_str.length() -1 -i] - '0';
}
// 判断和是否是8的倍数
if (sum % 8 == 0) {
return true;
}
return false;
}
int main() {
// 读入待处理的数字个数
int n;
std::cin >> n;
// 循环处理每个数字
for (int i = 0; i < n; i++) {
// 读入当前要判断的数字
long long number;
std::cin >> number;
// 判断并输出结果
if (is_lucky_num(number)) {
std::cout << 'T' << "\n";
} else {
std::cout << 'F' << "\n";
}
}
return 0;
}
{% include custom/custom-post-content-footer.md %}
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
“luogu-”系列题目可在 洛谷题库 在线评测。
“bcqm-”系列题目可在 编程启蒙题库 在线评测。
