選大王 約瑟夫問題

2021-10-03 09:28:15 字數 2911 閱讀 6098

3 參考**

選大王時間限制 1000 ms 記憶體限制 32768 kb **長度限制 100 kb 判斷程式 standard (來自 小小)

題目描述

有n只猴子,按順時針方向圍成一圈選大王(編號從1到n),從第1號開始報數,一直數到m,數到m的猴子退出圈外,剩下的猴子再接著從 1 開始報數。就這樣,直到圈內只剩下乙隻猴子時,這個猴子就是猴王。

現在告訴你 n 和 m,請幫忙求出哪乙隻猴子能當大王。

輸入描述:

輸入包含多組資料。

每組資料報含兩個正整數 n 和m(1≤ m < n ≤ 10000)。

輸出描述:

對應每一組輸入,輸出猴王的編號 i(1≤i≤n)。

輸入例子:

7 38 3

輸出例子:47

求最後剩下的猴子編號

約瑟夫問題

問題來歷

據說著名***歷史學家 josephus有過以下的故事:在羅馬人占領喬塔帕特後,39 個***人與josephus及他的朋友躲到乙個洞中,39個***人決定寧願死也不要被敵人抓到,於是決定了乙個***方式,41個人排成乙個圓圈,由第1個人開始報數,每報數到第3人該人就必須***,然後再由下乙個重新報數,直到所有人都***身亡為止。然而josephus 和他的朋友並不想遵從。首先從乙個人開始,越過k-2個人(因為第乙個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下乙個人留下,這個人就可以繼續活著。問題是,給定了人數總和,一開始要站在什麼地方才能避免被處決?josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

直接模擬

假設 對於n,m 已知 k 是當前需要***的人,當前序列為

0,1,… ,k-1, k , k+1, … , n-1

那麼剩下的人分別為

0,1,… ,k-1, k+1, … , n-1

接下來需要從 k+1 處開始報數,不妨對 k 以前的數 +n, 即:

n, n+1, … , n+k-1, k+1, … , n-1

按照報數順序排列:

k+1, … , n,n+1, … , n+k-1

這個序列可看出,僅比正常序列 0,1,… , n-2 多了 k+1

所以有:

假設 josephus(n,m)是序列 0,1,… , n-1迴圈報數最終剩下的人,

則 josephus(n-1,m)為序列 0,1,… , n-2迴圈報數最終剩下的人

josephus(n,m)= josephus(n-1,m)+k+1

考慮到運用上述公式時,是對 n,m序列 對k之前的數+n得到的,

因此應當修正為

josephus

(n,m)

=( josephus

(n-1

,m)+k+

1)%n

如此即可還原到原始序列。

又因為對於任意 n,m ,初始k值我們是可以求解得到的

k=

(m%n)

-1

所以

josephus

(n,m)

=( josephus

(n-1

,m)+

(m%n))%n

josephus

(n,m)

=( josephus

(n-1

,m)+m)%n

至此已形成遞迴

遞迴截至條件也顯而易見

josephus(1

,m)=

0

注意

此解法針對的是 0, 1, 2, … , n-1的序列,

但約瑟夫環一般是從1 開始的,即 1, 2, … , n

所以我們利用 josephus(n,m)求出的結果要 +1才是最終結果。

參考()

#include

#include

using std::vector;

vector<

int> a;

intmain

(int argc,

char

const

*ar**)

else

int pos = m -1;

while

(a.size()

>1)

int tsize =

(int

) a.

size()

; pos = pos % tsize;

}printf

("%d\n"

,a[0])

; a.

clear()

;}}return0;

}

#include

intjosephusrecursive

(int n,

int m)

return

(josephusrecursive

(n-1

,m)+m)

%n;}

intmain

(int argc,

char

const

*ar**)

// /*

// * 此解法針對的是 0, 1, 2, ... , n-1的序列,

//但約瑟夫環一般是從1 開始的,即 1, 2, ... , n

//所以我們利用 josephus(n,m)求出的結果要 +1才是最終結果。

// */

printf

("%d\n"

, r +1)

;}return0;

}

約瑟夫問題(猴子選大王)

問題描述 約瑟夫問題 有 只猴子,按順時針方向圍成一圈選大王 編號從 到 從第 號開始報數,一直數到 數到 的猴子退出圈外,剩下的猴子再接著從1 開始報數。就這樣,直到圈內只剩下乙隻猴子時,這個猴子就是猴王,程式設計求輸入 後,輸出最後猴王的編號。輸入資料 每行是用空格分開的兩個整數,第乙個是 n,...

猴子選大王 約瑟夫問題

例題描述 由m只猴子圍成一圈,從1到m進行編號,打算從中選出乙個大王,經過協商,決定選出大王的規則 從第乙個開始迴圈報數,數到n的猴子出圈,下乙個猴子從1開始報數。輸入樣例 3 2 輸出樣例 3方法一 模擬法 include using namespace std define max 100 lo...

約瑟夫問題,猴子選大王

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