約瑟夫問題

2021-06-27 01:23:51 字數 1454 閱讀 9532

約瑟夫問題:有n只猴子,按順時針方向圍成一圈選大王(編號從1到n),從第1號開始報數,一直數到m,數到m的猴子退出圈外,剩下的猴子再接著從1開始報數。就這樣,直到圈內只剩下乙隻猴子時,這個猴子就是猴王,程式設計求輸入n,m後,輸出最後猴王的編號。

每行是用空格分開的兩個整數,第乙個是 n, 第二個是 m ( 0 < m,n <=300)。最後一行是:

0 0對於每行輸入資料(最後一行除外),輸出資料也是一行,即最後猴王的編號

6 2

12 4

8 30 0

5

17

將n個人從0到n-1進行編號,則顯然第一次編號為k=(m-1)%n的同學掛了,第乙個同學掛了之後,剩餘的n-1個同學組成了乙個新的約瑟夫環。編號從k+1=m%n開始又重新報數。

k+1  =>   0

k+2 =>   1

k+3 =>   2

.......

.......

k-2  => n-2

k-1  => n -1

剩餘的n - 1個同學又組成了乙個新的joseph環,對新環來說,編號k = (m - 1) % (n - 1)的同學會掛,如此下去,這裡面似乎有某種規律可尋。

考慮到不會死的同學一直不會被殺(廢話),我們設i個同學時的不會掛的同學的編號(即解)為x,那麼當死掉乙個同學剩餘i - 1個同學的時候,x仍然不會被殺,但此時的x已經由編號變換變成了x』,即x』是i - 1的情況時的解!一直推下去直到i - (i - 1)即1的情況,那1的時候解明顯是0嘛!(注意編號是從0開始的),倒推回來,那問題不就解決了麼!

好了,分析清楚了剩下的就只是數學推導了,

向下變換:x'= (x - (k + 1)) % i;

向上變換:x = (x'+(k + 1))% i;

其中:  k = (m - 1) % i;

帶入可得:x = (x'+ m) % i;

如何知道(n-1)個人報數的問題的解?對,只要知道(n-2)個人的解就行了。(n-2)個人的解呢?當然是先求(n-3)的情況 ---- 這顯然就是乙個倒推問題!好了,思路出來了,下面寫遞推公式:

令f[i]表示i個人玩遊戲報m退出最後勝利者的編號,最後的結果自然是f[n]

遞推公式

f[1]=0;

f[i]=(f[i-1]+m)%i; (i>1)

有了這個公式,我們要做的就是從1-n順序算出f[i]的數值,最後結果是f[n]。

#include#include#include #include#includeusing namespace std;

void fun();

int main()

void fun()

{ int n,m,s,i;

while(cin>>n>>m&&(m||n))

{ s=0;

for(i=2;i<=n;i++)

s=(s+m)%i;

cout<

約瑟夫問題 約瑟夫環

約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...

約瑟夫問題 約瑟夫環

約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...

約瑟夫問題

這是17世紀的法國數學家加斯帕在 數目的遊戲問題 中講的乙個故事 15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其餘的人才能倖免於難,於是想了乙個辦法 30個人圍成一圓圈,從第乙個人開始依次報數,每數到第九個人就將他扔入大海,如此迴圈進行直到僅餘15個人為止。問怎樣排法,才能使每次...