題意#
此為經典的「約瑟夫問題(Josephus Problem)」。
\( n \) 個人圍成一圈,編號為 1 到 \( n \)。
從 1 號開始報數,規則為「跳過一個人,淘汰下一個人」。
過程持續進行,直到所有人皆被淘汰為止。
需要依序輸出被淘汰的人的編號。
思路#
由於 \( n \) 的範圍不大且淘汰規則固定為「跳過一、淘汰一」,可使用佇列(Queue)直接模擬報數過程。
初始時將 1 到 \( n \) 依序推入 Queue。
當 Queue 中尚有元素時,反覆執行以下兩個步驟:
- 跳過第一個人:將排頭移至 Queue 尾端(先
push排頭,再將其pop)。 - 淘汰第二個人:輸出此時的排頭編號,並將其移出 Queue(直接
pop)。
利用 Queue 模擬環狀結構,持續進行直到 Queue 為空,輸出的序列即為完整的淘汰順序。
程式碼#
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define INF LONG_LONG_MAX/1000
#define WA() cin.tie(0)->sync_with_stdio(0)
#define all(x) (x).begin(), (x).end()
#define int long long
#define PII pair<int, int>
signed main() { WA();
int n; cin >> n;
// 使用 Queue 來模擬圍成一圈的人
queue<int> q;
// 一開始把 1 ~ n 的人都依序排進隊伍裡
for (int i = 1; i <= n; i++) q.push(i);
// 若 Queue 中尚有未淘汰者,持續模擬
while (q.size()) {
// 第一個人跳過:移至隊伍尾端
q.push(q.front());
q.pop();
// 第二個人淘汰:印出它的編號並移出隊伍
cout << q.front() << ' ';
q.pop();
}
}
