for (int i = 1; i <= m; i++) {
if (now + 1 > n) now = 1;
else ++now;
if (ar[now]) --i; // 已出局者跳過計數
if (!(ar[now]) && i == m)
ar[now] = 1; // 標記出局
}
--out;
問題:ar 初始化為 0 代表在圈內,1 代表出局。但邏輯中 if (ar[now]) --i; 導致計數器回退,配合外層 while (out-1) 易陷入無限迴圈或跳過正確位置。
int n, m, p; // 總數、步長、起始位置
int *ar = calloc(n + 1, sizeof(int)); // 0=在圈內, 1=出局
int remain = n;
int pos = p - 1; // 0-based 索引方便取模
while (remain > 1) {
int step = 0;
while (step < m) {
pos = (pos + 1) % n; // 環狀移動
if (pos == 0) pos = n; // 1~n 映射
if (ar[pos] == 0) // 僅對在圈內者計數
++step;
}
ar[pos] = 1; // 標記出局
--remain;
}
// 找出剩餘的唯一 0
for (int i = 1; i <= n; ++i)
if (ar[i] == 0) { printf("%d\n", i); break; }
free(ar);
每次刪除節點只需調整指標,無需掃描已出局位置,適合大數據量。
f(1)=0; f(i)=(f(i-1)+m)%i)O(n) 直接算出結果。