{}
CYBER CYBER CYBER CYBER CYBER
66
%OFF
Week Week Week Week Week

Stop copy pasting code you don't actually understand

Build the coding confidence you need to become a developer companies will fight for

Stop copy pasting code you don't actually understand

Become a PRO
Become a PRO
CYBER CYBER CYBER CYBER CYBER
66
%OFF
Week Week Week Week Week

Stop copy pasting code you don't actually understand

Build the coding confidence you need to become a developer companies will fight for

Stop copy pasting code you don't actually understand

Become a PRO
Become a PRO
run-icon
main.cpp
/* // 這裡是原本的暴力模擬版本 (用 vector.erase),時間複雜度太高,所以被註解掉 #include <iostream> #include <vector> using namespace std; int main() { int N, M, K; cin >> N >> M >> K; vector<int> circle(N); for (int i=0;i<N;i++) circle[i] = i + 1; // 初始化圈子 [1..N] int pos = 0; for (int boom = 1; boom <= K; boom++) { pos = (pos + M - 1) % circle.size(); // 找到要淘汰的位置 //cout << "淘汰 " << circle[pos] << endl; if (boom == K) { int lucky = circle[(pos + 1) % circle.size()]; // 找到最後幸運者 cout << lucky << endl; return 0; } circle.erase(circle.begin() + pos); // 淘汰該人 (O(N)) if (pos == circle.size()) pos = 0; // 如果剛好刪到最後一個,重置 pos } } */ #include <bits/stdc++.h> // 匯入所有標準函式庫 using namespace std; // Fenwick Tree (Binary Indexed Tree) 結構 struct Fenwick { int l; // 陣列大小 (總人數) vector<int> temp; // Fenwick Tree 的內部陣列 (用來維護活著的人數) // 建構子:初始化長度 l,並建立一個長度 l+1 的陣列 (1-based) Fenwick(int l): l(l), temp(l+1,0) {} // 在位置 i 加上 val (更新 Fenwick Tree) void add(int i,int val){ for(; i<=l; i+=i&-i){ // i += i&-i 代表跳到下一個負責的節點 temp[i]+=val; // 更新節點值 } } // 查詢前 i 個元素的總和 (這裡命名為 all) int all(int i){ int s=0; for(; i>0; i-=i&-i) { // i -= i&-i 代表往上跳到父節點 s+=temp[i]; // 累加區間和 } return s; } // 找到第 k 個活著的人 (order statistic) int begin(int k){ int NotHere=0; // 當前已經確定不包含答案的區間右端點 // mask = 小於等於 l 的最大 2 的冪次 for(int mask=1<<(31-__builtin_clz(l));mask!=0;mask/=2){ int next=NotHere+mask; // 嘗試往右跳 mask if(next<=l && temp[next]<k){ // 如果這段區間的總和 < k,代表答案在更右邊 k-=temp[next]; // 扣掉這段的數量 NotHere=next; // 更新目前位置 } } return NotHere+1; // 回傳第 k 個活著的人的原始編號 } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N,M,K; cin>>N>>M>>K; // 輸入人數 N、間隔 M、爆炸次數 K Fenwick fw(N); // 建立一個 Fenwick Tree,大小 N for(int i=1;i<=N;i++) fw.add(i,1); // 初始化:每個人都活著 (值=1) int alive=N; // 當前活著的人數 int pos=0; // 當前炸彈所在位置 (以活著的人數排名為基準,0-based) for(int boom=1; boom<=K; boom++){ // 模擬 K 次爆炸 pos=(pos+M-1)%alive; // 找到要淘汰的順位 (第 pos 個活著的人) int eliminated=fw.begin(pos+1); // 找到該順位對應的原始編號 fw.add(eliminated,-1); // 把這個人標記為淘汰 (設為 0) alive--; // 活著的人數減 1 if(boom==K){ // 如果是第 K 次爆炸 int luckyIndex=(pos%alive)+1; // 下一位 (1-based) int lucky=fw.begin(luckyIndex); // 找到幸運者的原始編號 cout<<lucky<<"\n"; // 輸出幸運者 return 0; // 結束程式 } } }
Output