CPE 一顆星
題目連結:https://zerojudge.tw/ShowProblem?problemid=c108
內容
一群人圍成一個圈圈(編號從1, 2, 3, …, n),然後開始數,第 m 個人要被吃掉(第一次從編號1的人開始數)。
現在假設共有2k個人,其中排在編號 1 到 k 的是好人,排在編號 k+1 到 2k 的是壞人,你的任務就是要找出一個最小的 m,使得在所有 k 個壞人被吃掉之前,沒有一個好人會被吃掉。
每一列有一個整數 k (0 < k < 14)。
k = 0 結束。
範例輸入
3
4
0
範例輸出
5
30
想法
枚舉所有可能的 m 值,觀察後發現
m > k (否則第一輪就取到好人)。
(m-1) % 2*k >= k (一樣看第一輪)。
如果上述兩條件成立,就可以開始取人了,取到好人就直接跳掉,接著判斷下一個 m。
可在一開始使用一個陣列儲存所有 k 對應的 m ,詢問時就可直接印出。
參考資料:YUI HUANG 演算法學習筆記, inversion的小屋
程式碼
    
    
        1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   | #include <bits/stdc++.h> #define fastio ios_base::sync_with_stdio(false), cin.tie(nullptr) using namespace std;
  int main(){     fastio;     int m, kill, ans[14], total;     bool suc;     for(int i = 1; i < 14; ++i){         suc = false;         m = i;         total = i << 1;         while(!suc){             ++m;             if(i == 1) suc = true;             if((m-1)%total >= i){                 kill = (m-1) % total;                  for(int c = 2; c <= i; ++c){                     kill = (kill+m-1) % (total-c+1);                     if(kill < i) break;                     if(c == i) suc = true;                 }             }         }         ans[i] = m;     }     int k;     while(cin >> k && k){         cout << ans[k] << "\n";     }     return 0; }
   |