約瑟夫問題:有n只猴子,按順時針方向圍成一圈選大王(編號從1到n),從第1號開始報數,一直數到m,數到m的猴子退出圈外,剩下的猴子再接著從1開始報數。就這樣,直到圈內只剩下乙隻猴子時,這個猴子就是猴王,程式設計求輸入n,m後,輸出最後猴王的編號。
每行是用空格分開的兩個整數,第乙個是 n, 第二個是 m ( 0 < m,n <=300)。最後一行是:
0 0對於每行輸入資料(最後一行除外),輸出資料也是一行,即最後猴王的編號
6 212 4
8 30 0
517
將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個人為止。問怎樣排法,才能使每次...