题目
模拟求解经典约瑟夫环问题(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