#46317: C++解法


s290006@student.cysh.cy.edu.tw (風堇一生推)

學校 : 國立嘉義高級中學
編號 : 263344
來源 : [163.27.3.90]
最後登入時間 :
2025-10-03 13:06:32

不用開陣列來存每個人的狀態(這是我一開始的想法)

其實可以利用一個特性:直接用變數存爆炸的「位子」

 

舉例 範測中 1 2 3 4 5 是2爆掉

變成1 3 4 5

然後拿炸彈的是第二個位子 3

 

接著4爆掉 變成1 3 5

爆炸的位子是3 所以是5拿下一個炸彈

 

接著1爆掉 變成3 5

爆炸的位子是1 但只會報三次 所以是3贏

 

現在回頭看 問題點就在要怎麼處理傳到最後一個位置後的下一個點

其實解決方法很簡單 就直接用%(取餘)

所以如果我今天要寫遞迴來處理這題:

//我使用0-index來解 所以編號應該是0 1 2 3 4 在傳炸彈時第一位需考慮 所以m要先-1

一樣舉例範測

m先減一 把第一個人減掉(小細節)

第一次遞迴 n=5 m=1 k=3

0 1 2 3 4 初始index=0

index=(index+m)%n=(0+1)/5=1 1爆 index=1

0 2 3 4

第二次遞迴 n=4 m=1 k=2(n是人數 取餘裡需要用到 k則是單純記數 沒有用)

index=(index+m)%n=(1+1)%4=2 3爆 index=2

0 2 4
第三次遞迴 n=3 m=1 k=1
index=(2+1)%3=0  0爆 index=0

2 4

最後待在index=0的2 獲得勝利

 

而我們用一樣的邏輯去寫後會發現:

int in(int n,int m,int k){

if(k==0) return m%n;

return (in(n+1,m,k-1)+m)%n;

}

 

 

int main(){

cin>>n>>m>>k;

m--;

cout<<in(n-k+1,m,k-1)+1;

}

跑出來的僅僅是「最後的炸彈位置」而非「最後位置上的人」

這是因為我們是正向跑計算

而因為變數是可以累加的,有交換律,所以我們用反向跑遞迴

最後的那個位置對應的就會剛好是那個人

 

完整程式碼(前面標頭檔啥的不寫了):

int n,m,k;

 

int change(int n,int m,int t){

if(t==k) return m%n;

return (change(n-1,m,t+1)+m)%n;

}

 

int main(){

cin>>n>>m>>k;

cout<<change(n,m,1)+1;

}

參考清大電神們的code 他們最一開始直接丟k進函式 就又少了一個變數t

只不過我個人覺得比較好算 所以還是留下來了