【例2-3】围圈报数

GitHub跳转原题关系图返回列表

用队列模拟约瑟夫环:未数到 m 的人移到队尾,数到 m 的人出列输出。

OJ: roj

题目 ID: 1334

难度:入门

标签:模拟队列约瑟夫问题

创建: 2026-09-30 05:43

更新: 2026-10-05 10:11

题目描述

nn 个人围成一圈,编号 1∼n1\sim n。从第 11 个人开始顺时针报数,数到第 mm 的人出列,然后从下一位重新开始报数,直到所有人出列。输出出列顺序。

输入:nn 和 mm。输出:出列顺序。数据范围:n⩽100n\leqslant 100。

思路

把当前在圈内的人按顺序放进队列。每次取队头报数,未数到 mm 就放回队尾,数到 mm 就出列输出,直到队列为空。

参考代码

Python 版:

python
#!/usr/bin/env python3
# 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-09-30 05:43
# update_at: 2026-09-30 05:43

import sys
from collections import deque


def josephus(n: int, m: int) -> list[str]:
    """模拟围圈报数,返回出列顺序。"""
    q: deque[int] = deque(range(1, n + 1))
    ans: list[str] = []
    cnt = 0
    while q:
        x = q.popleft()
        cnt += 1
        if cnt == m:
            ans.append(str(x))
            cnt = 0
        else:
            q.append(x)
    return ans


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    n, m = next(data), next(data)
    print(' '.join(josephus(n, m)))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

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-10-05 10:10
 * update_at: 2026-10-05 10:11
 */
#include <iostream>
#include <queue>
using namespace std;

typedef long long ll;

queue<ll> q; // 当前仍在圈内的人,队头为正在报数的人

int main() {
    ll n, m;
    cin >> n >> m;
    for (ll i = 1; i <= n; ++i) q.push(i); // 初始围圈顺序 1~n

    ll cnt = 0; // 当前已报数到第几个
    while (!q.empty()) {
        ll x = q.front();
        q.pop();
        ++cnt;
        if (cnt == m) { // 正好数到第 m 个人,出列输出
            cout << x;
            cnt = 0;
            if (!q.empty()) cout << ' ';
        } else { // 未数到 m,回到队尾等待下一轮
            q.push(x);
        }
    }
    cout << '\n';
    return 0;
}