【2023 GESP四级题解析】幸运数(洛谷B3850):解题思路与代码详解
4天前
一、题目解读
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-拆位求和”抽象为独立函数,提升代码可读性;
该解法兼顾算法逻辑与代码简洁性,适合竞赛与算法学习参考。
原创内容 转载请注明出处