8 数位处理与逻辑模拟(一)

正在加载视频播放器…

GESP C++ 二级:数位处理与逻辑模拟综合

核心目标:掌握数位拆分核心技术,理解逻辑模拟的方法论,能综合运用循环、分支、数位处理解决模拟类问题,熟悉GESP二级高频真题的解题思路。
数位处理靠“取余取位、整除去位”;逻辑模拟靠“忠实复现题目描述的规则和流程”;两者结合,就是GESP二级编程题的核心考查方向。

第一部分:数位处理核心技术与高频题型

数位处理是GESP二级编程题中出现频率最高的考点之一。核心操作只有两个:% 10 取个位,/ 10 去个位。

1. 数位处理六大题型

题型 核心操作 典型真题
求各位数字之和 循环累加 n % 10 [GESP202412 二级] 寻找数字
求数字个数(位数统计) 循环计数,注意0特判 拆数类题目
数字反转 rev = rev * 10 + n % 10 逆序数问题
数位统计(统计某数字出现次数) 逐位判断是否等于目标值 [GESP202603 二级] 数数
特殊数字判断(水仙花数/自幂数) 数位拆分 + 幂运算 [GESP202306 二级] 自幂数判断
数位比较(回文数/平衡数/递增数) 拆分后比较或反转比较 回文数、平衡数

2. 标准数位处理模板

// 模板1:数位求和
int digitSum(int n) {
    int sum = 0;
    while (n > 0) {
        sum += n % 10;
        n /= 10;
    }
    return sum;
}

// 模板2:数字反转
int reverseNum(int n) {
    int rev = 0;
    while (n > 0) {
        rev = rev * 10 + n % 10;
        n /= 10;
    }
    return rev;
}

// 模板3:统计某数字出现次数
int countDigit(int n, int target) {
    int cnt = 0;
    while (n > 0) {
        if (n % 10 == target) cnt++;
        n /= 10;
    }
    return cnt;
}

// 模板4:位数统计(注意0特判)
int digitCount(int n) {
    if (n == 0) return 1;
    int cnt = 0;
    while (n > 0) {
        cnt++;
        n /= 10;
    }
    return cnt;
}

3. 真题示例:数位和为7的倍数

题目来源:GESP 2024年9月 二级真题“数位之和”

题目要求:输入n个整数,对每个数求各位数字之和,判断是否为7的倍数。

#include <cstdio>
using namespace std;

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        long long a;
        scanf("%lld", &a);
        int sum = 0;
        while (a > 0) {
            sum += a % 10;
            a /= 10;
        }
        if (sum % 7 == 0)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

考试提示:当输入数据量较大(如10^5次)时,cin/cout 可能超时,建议使用 scanf/printf 提升效率。

4. 真题示例:自幂数判断

题目来源:GESP 2023年6月 二级真题“自幂数判断”

自幂数:一个n位数,其各位数字的n次方之和等于它本身。

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    long long n;
    cin >> n;
    long long t = n;
    int digits = 0;
    while (t > 0) { digits++; t /= 10; }
    
    t = n;
    long long sum = 0;
    while (t > 0) {
        int d = t % 10;
        sum += (long long)pow(d, digits);
        t /= 10;
    }
    if (sum == n) cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}

5. 真题示例:数数

题目来源:GESP 2026年3月 二级真题“数数”

题目要求:判断正整数n的所有数位中是否包含恰好3个2。

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int cnt = 0;
    int t = n;
    while (t > 0) {
        if (t % 10 == 2) cnt++;
        t /= 10;
    }
    if (cnt == 3) cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}

这类题目考察的是嵌套循环与数位分离的综合运用:外层遍历范围,内层拆解数字,统计满足条件的数字。

第二部分:逻辑模拟方法论

6. 什么是逻辑模拟

模拟算法是GESP二级最具实践价值的模块,强调将现实问题流程逐行映射为代码指令,不依赖数学公式推导,而依靠程序精确控制每一步状态变迁。

模拟类题目在GESP真题中占比超过35%,且极易因“状态遗漏”或“时序错乱”导致全盘错误。

7. 模拟算法的核心步骤

分析问题 → 识别状态变量 → 确定状态更新规则 → 确定终止条件 → 编写循环/分支 → 验证边界
步骤 说明 示例
识别状态变量 哪些量会随过程变化 位置x/y、方向dir、剩余步数step
确定更新规则 每一步如何改变状态 每步x += dx, y += dy
确定终止条件 什么时候停止 步数用完、到达终点、条件满足
处理边界 越界、碰撞、非法输入 坐标越界检查、除零检查
调试 打印每步状态辅助纠错 cout << "step:" << step << " x:" << x;

8. 常见模拟模型

模型 状态变量 典型题目
数字变换游戏 当前数字 卡拉兹猜想、数字黑洞
日历星期推算 天数、星期 日期计算
迷宫行走 x, y, 方向 小球滚动路径
排队叫号系统 队列状态、当前号 银行叫号
矩阵遍历 行i、列j X字矩阵、N字矩阵

9. 真题示例:数字黑洞

题目来源:GESP 2023年9月 二级真题“数字黑洞”

数字黑洞:对一个数字,将其各位数字重新排列成最大数和最小数,相减,重复直到得到固定值。

#include <iostream>
#include <algorithm>
using namespace std;

int main() {
    int n;
    cin >> n;
    int cnt = 0;
    while (n != 495 && n != 6174) {  // 3位数黑洞495,4位数黑洞6174
        int digits[4], t = n, len = 0;
        while (t > 0) { digits[len++] = t % 10; t /= 10; }
        
        // 补零到位数统一
        while (len < 4) digits[len++] = 0;
        
        sort(digits, digits + 4);
        
        int minNum = 0, maxNum = 0;
        for (int i = 0; i < 4; i++) {
            minNum = minNum * 10 + digits[i];
            maxNum = maxNum * 10 + digits[3 - i];
        }
        
        n = maxNum - minNum;
        cnt++;
    }
    cout << cnt << endl;
    return 0;
}

模拟要点:每一步都要忠实复现规则——拆位、排序、组合最大最小数、相减,一步不能少。

10. 真题示例:卡拉兹猜想

题目要求:对正整数n,若为偶数则除以2,若为奇数则(3n+1)除以2,重复直到n=1,统计次数。

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int cnt = 0;
    while (n != 1) {
        if (n % 2 == 0)
            n /= 2;
        else
            n = (3 * n + 1) / 2;
        cnt++;
    }
    cout << cnt << endl;
    return 0;
}

这是最典型的逻辑模拟:规则清楚,只需按规则一步步执行,不需要任何数学推导。

第三部分:数位处理与逻辑模拟综合应用

11. 综合题解题框架

┌─────────────────────────────────────┐
│ 外层循环:遍历范围或重复模拟次数      │
│   ├─ 输入/初始化状态变量              │
│   ├─ 内层循环:数位拆分 / 状态更新    │
│   ├─ 条件判断:筛选/计数/累加          │
│   └─ 输出/更新结果                    │
└─────────────────────────────────────┘

12. 综合模型一:遍历范围内数位满足条件的数

题目:输出1~n中,数位之和为偶数的所有数。

for (int i = 1; i <= n; i++) {
    int t = i, sum = 0;
    while (t > 0) {
        sum += t % 10;
        t /= 10;
    }
    if (sum % 2 == 0) {
        cout << i << " ";
    }
}

考点:外层遍历 + 内层数位拆分 + 条件判断。

13. 综合模型二:模拟数字变换过程

题目:从n开始,每次将n替换为其数位之和,直到n为一位数,输出最终结果和步数。

int n;
cin >> n;
int steps = 0;
while (n >= 10) {
    int sum = 0;
    while (n > 0) {
        sum += n % 10;
        n /= 10;
    }
    n = sum;
    steps++;
}
cout << n << " " << steps << endl;

14. 综合模型三:好数判断(数位与位数关系)

题目:好数是指数字的数位之和是位数的倍数。

int n;
cin >> n;
int t = n, sum = 0, digits = 0;
while (t > 0) {
    sum += t % 10;
    t /= 10;
    digits++;
}
if (sum % digits == 0) cout << "Yes" << endl;
else cout << "No" << endl;

15. 综合模型四:平衡数判断

题目:平衡数是指奇数位数字之和与偶数位数字之和相等。

int n;
cin >> n;
int t = n, pos = 1, oddSum = 0, evenSum = 0;
while (t > 0) {
    int d = t % 10;
    if (pos % 2 == 1) oddSum += d;
    else evenSum += d;
    t /= 10;
    pos++;
}
if (oddSum == evenSum) cout << "Yes" << endl;
else cout << "No" << endl;

16. 综合模型五:递增数判断

题目:递增数是指数字从左到右每一位高位数字比低位数字小。

int n;
cin >> n;
int last = 10;  // 比任何一位数字都大
bool ok = true;
while (n > 0) {
    int d = n % 10;  // 从个位开始取(相当于从右往左)
    if (d >= last) {  // 右边应比左边小
        ok = false;
        break;
    }
    last = d;
    n /= 10;
}
if (ok) cout << "Yes" << endl;
else cout << "No" << endl;

注意:从右往左取数位时,判断条件要反过来理解——先取的是最低位,后取的是更高位,递增要求高位 < 低位。

第四部分:易错点与调试技巧

17. 数位处理易错点

  1. 忘记特判0:0的位数是1,不是0。while (n > 0) 对0不执行。
  2. 变量被修改后无法再用:数位拆分时会修改原数,需要用临时变量 int t = n; 保存。
  3. 数字反转溢出:反转后的数可能超出 int 范围,大数用 long long。
  4. 取位顺序搞反:n % 10 先取个位(最低位),不是最高位。
  5. 数位比较方向错误:从右往左取位时,递增/递减的判断方向要相应调整。

18. 逻辑模拟易错点

  1. 状态遗漏:模拟过程中某些状态没有更新,导致结果错误。
  2. 时序错乱:状态更新的顺序影响结果,先更新谁后更新谁要想清楚。
  3. 终止条件错误:死循环或提前退出。
  4. 边界未处理:坐标越界、除零、输入为0等特殊情况。
  5. 输出格式错误:换行、空格、大小写不符合题目要求。

19. 调试技巧

打印中间状态:在循环内插入输出语句,观察每一步的变量变化。

while (n > 0) {
    int d = n % 10;
    cout << "digit=" << d << " n=" << n << endl;  // 调试输出
    // ...
    n /= 10;
}

小数据验证:用简单输入(如n=1、n=10、n=0)先验证程序基本逻辑,再测试大数据。

总结

数位处理与逻辑模拟是GESP二级编程题的核心考查方向。

  1. 数位处理核心:% 10 取个位,/ 10 去个位。
  2. 数位拆分时用临时变量保存原数。
  3. 0的位数是1,注意特判。
  4. 数字反转用 rev = rev * 10 + n % 10。
  5. 逻辑模拟的关键是“忠实复现题目描述”。
  6. 模拟前先识别状态变量和更新规则。
  7. 模拟类题目占比高,必须熟练掌握。
  8. 调试时打印中间状态,小数据验证。
  9. 大数据输入用 scanf/printf 提升效率。
  10. 综合题 = 外层遍历 + 内层数位处理 + 条件判断。