题目

模拟求解经典约瑟夫环问题(Josephus Problem):n 个人围成一圈(编号 1 到 n),从第 1 个人开始报数,数到 m 的人出列淘汰,下一个人重新从 1 开始报数,直到所有人出列。输出所有人的出列顺序。

输入格式:一行输入两个正整数 n 和 m,以空格分隔。

输出格式:按出列次序输出编号,每个编号后跟空格,末尾换行。

数据范围与约定:1 ≤ n ≤ 100,1 ≤ m ≤ 100。

思路与算法

1. 环形数组模拟
开辟数组 vis[n + 1] 记录淘汰状态(0 表示在圈内,1 表示已淘汰)。

2. 报数与环形绕回
使用指针 idx = (idx % n) + 1 实现首尾相接环形遍历;遇到未淘汰人员时报数计数器 count++,当 count == m 时标记淘汰并打印输出,循环直到全部淘汰。

完整程序

#include <stdio.h>

int main(void)
{
    int n, m;
    if (scanf("%d %d", &n, &m) != 2 || n < 1 || m < 1) {
        return 1;
    }

    // 约瑟夫环模拟:1 表示在圈内,0 表示已淘汰
    int alive[1000];
    for (int i = 0; i < n; i++) {
        alive[i] = 1;
    }

    int left = n, i = 0, cnt = 0;
    while (left) {
        // 仅对圈内活人报数
        if (alive[i]) {
            cnt++;
            // 报到 m 的人出圈
            if (cnt == m) {
                printf("%d ", i + 1);
                alive[i] = 0;
                left--;
                cnt = 0;
            }
        }
        // 环状前进:通过取模循环回到圈首
        i = (i + 1) % n;
    }
    putchar('\n');
    return 0;
}

运行示例

输入:

5 2

输出:

2 4 1 5 3