約瑟夫問題大意就是給你n個人,編號為1-n。從第乙個人開始報數,報到m時候,第m個人出列。然後下個人從1開始報數,逢m出列。問最後出列的人的編號。
剛開始用的是迴圈鍊錶,純模擬做法。發現當n很大時,鐵定tle。所以上網搜了下,發現有數學方法解決這個問題。
思路就是遞推,發現子問題,然後由子問題的解推總問題的解。
公式就是:
f(1) = 0;
f(i) = (f(i - 1) + m) % i; (i > 1)
公式的含義我解釋一下:
f(1)代表就乙個人玩遊戲,所以不需要踢人,第乙個人就是獲勝者,但為什麼是0不是1本身呢?接著看。。。。。
f(i)代表剩i個人時要踢的人,f(i - 1)代表剩i - 1時踢掉的人,從這個人的下乙個即(f(i - 1) + 1)開始,數m個人,但是從(f(i - 1) + 1)開始時,(f(i - 1) + 1)已經有乙個人,所以下一次要踢掉的人就是(f(i - 1) + 1) + m - 1.。。這個應該可以理解。。。。那結果就是f(i - 1) + m。。因為可以把約瑟夫問題看成乙個圈圈,所以取余是必要的,防止出界。加入n = 8, 那麼要踢掉第10個人,其實就是踢掉 10 mod 8 = 2,第二個人。。。。
然後比較容易錯的地方就是剛才那個問題,為什麼f(1)不是1而是0呢?因為f(i)代表剩i個人時要踢的人,而1個人玩的時候就不需要踢人。同理,下面f(i)踢掉了乙個人,這樣,到最後,一共踢掉n-1個人,這個遊戲就結束了,獲勝者就是踢掉最後乙個人之後剩下的那個。因為踢掉乙個n就-1,所以最後剩2個人,踢掉乙個之後需要+1 mod n(總人數)。這樣,就可以求出獲勝者。
結果就是:
1個人時候,結果為 f(1) + 1.
大於乙個人的時候,結果為f(n) + 1;
至此,這個問題就解決了。。。。。。。。
**如下:
#include#include#include#include#includeusing namespace std; int main() printf("%d\n", ans + 1); //易錯點 } return 0; }
約瑟夫問題 約瑟夫環
約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...
約瑟夫問題 約瑟夫環
約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...
約瑟夫問題
這是17世紀的法國數學家加斯帕在 數目的遊戲問題 中講的乙個故事 15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其餘的人才能倖免於難,於是想了乙個辦法 30個人圍成一圓圈,從第乙個人開始依次報數,每數到第九個人就將他扔入大海,如此迴圈進行直到僅餘15個人為止。問怎樣排法,才能使每次...