报数

按自然数顺序模拟轮次,分别检查 7 的倍数和十进制数字 7。

OJ: shumeng

题目 ID: CSP201912A

难度:入门

标签:模拟数位

日期: 2026-07-31 16:21

形式化题目

四个人从 11 开始按顺序轮流报数。若当前数 xx77 的倍数或十进制表示含数字 77 则跳过并记在当前轮次玩家的跳过次数上;否则算作报出一个有效数字。累计报出 nn 个有效数字后停止,输出四人各自跳过的次数。

思路

逐个枚举自然数

11 开始递增枚举,编号 number 对应的玩家为 (number-1) % 4。先判断它是否为 77 的倍数,再逐位判断是否含 77

结束条件

跳过则增加当前玩家计数,否则增加有效报数个数,达到 nn 后立即结束。轮次始终随自然数推进,不能因跳过而换回同一位玩家。

代码

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-31 16:21
 * update_at: 2026-08-17 22:41
 */
#include <bits/stdc++.h>
using namespace std;

// 判断数字 number 是否应该跳过:是 7 的倍数,或十进制表示中含有数字 7。
bool should_skip(int number) {
    if (number % 7 == 0) return true;
    while (number > 0) {
        if (number % 10 == 7) return true;
        number /= 10;
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    int skipped[4] = {};  // 甲乙丙丁四人各自跳过的次数
    int said_count = 0;   // 已经真正报出的数字个数
    for (int number = 1; said_count < n; number++) {
        int player = (number - 1) % 4; // 当前数字轮到谁
        if (should_skip(number)) {
            skipped[player]++;
        } else {
            said_count++;
        }
    }
    for (int i = 0; i < 4; i++) cout << skipped[i] << '\n';

    return 0;
}

复杂度

设停止时枚举到的最大数字为 TT,时间复杂度 O(TlogT)O(T\log T),空间复杂度 O(1)O(1)。本题数据很小,直接模拟即可。

总结

游戏结束条件只统计真正报出的数字,不统计跳过次数。轮次始终随自然数推进,不能因跳过而换回同一位玩家。