【2023 GESP四级题解析】幸运数(洛谷B3850):解题思路与代码详解

一、题目解读
2023年GESP四级题“幸运数”(对应洛谷B3850)要求判断给定数字是否为“幸运数”。题目定义幸运数的规则为:将数字的奇数位(从右往左编号,个位为第1位)数字进行特定变换(乘以7后重复求和至数字≤9),最终所有数字位之和若为8的倍数,则该数为幸运数。例如,数字“12345”中奇数位为1和3,变换后求和判断是否为幸运数。题目需高效处理多组数据,考验位运算与数学变换能力。
二、解题思路
分步处理策略:
1. 位分离与变换:将数字转换为字符串,从末尾(个位)开始遍历,利用字符转数字获取每位值。
2. 奇数位处理:通过位置奇偶性判断,奇数位调用transformDigit函数进行“乘7-重复求和”变换,偶数位保持不变。
3. 求和与判断:累加变换后的各位数字,最终通过模8运算判定结果。
核心逻辑在于将复杂变换封装为独立函数,简化主流程,并利用字符串处理灵活遍历位序。
三、解题步骤解析
1. 输入处理:主函数接收测试用例数N,循环处理每组数字。
2. 转换奇数位:调用transformDigit对奇数位数字处理:
乘7;
循环拆解数字为各位和(如34→3+4=7),直至结果≤9。
3. 求和与判定:遍历数字字符串,奇数位应用变换结果,累加各位和,最后检查sum%8==0。
4. 输出结果:根据判定输出"T"或"F"。
四、代码与注释
#include <iostream>
#include <string>
using namespace std;
// 处理奇数位数字变换
int transformDigit(int digit) {
digit *= 7; // 先乘以7
// 循环处理直到数字不大于9
while (digit > 9) {
int sum = 0;
// 计算各位数字之和
while (digit > 0) {
sum += digit % 10;
digit /= 10;
}
digit = sum;
}
return digit;
}
// 判断是否为幸运数
bool isLuckyNumber(long long num) {
string s = to_string(num);
int sum = 0;
// 从个位开始(第1位),所以从字符串末尾开始处理
for (int i = s.length() - 1, pos = 1; i >= 0; i--, pos++) {
int digit = s[i] - '0';
// 奇数位进行变换,偶数位保持不变
if (pos % 2 == 1) {
digit = transformDigit(digit);
}
sum += digit;
}
// 判断和是否是8的倍数
return sum % 8 == 0;
}
int main() {
int N;
cin >> N;
while (N--) {
long long num;
cin >> num;
if (isLuckyNumber(num)) {
cout << "T" << endl;
} else {
cout << "F" << endl;
}
}
return 0;
}五、总结
本文解析的GESP四级题“幸运数”解法,通过以下关键点实现高效求解:
1. 位序与奇偶性判断:利用字符串逆序遍历自然对应奇数位;
2. 数学变换封装:将“乘7-拆位求和”抽象为独立函数,提升代码可读性;
3. 模运算优化:直接求和后模8判断,避免中间结果溢出。
该解法兼顾算法逻辑与代码简洁性,适合竞赛与算法学习参考。
原创内容 转载请注明出处
