約瑟夫環問題詳解

2021-12-30 01:07:55 字數 3511 閱讀 4921

講乙個比較有意思的故事:約瑟夫是猶太軍隊的乙個將軍,在反抗羅馬的起義中,他所率領的軍隊被擊潰,只剩下殘餘的部隊40餘人,他們都是寧死不屈的人,所以不願投降做叛徒。一群人表決說要死,所以用一種策略來先後殺死所有人。

於是約瑟夫建議:每次由其他兩人一起殺死乙個人,而被殺的人的先後順序是由抽籤決定的,約瑟夫有預謀地抽到了最後一簽,在殺了除了他和剩餘那個人之外的最後一人,他勸服了另外乙個沒死的人投降了羅馬。

我們這個規則是這麼定的:

在一間房間總共有n個人(下標0~n-1),只能有最後乙個人活命。

按照如下規則去殺人:

所有人圍成一圈 順時針報數,每次報到q的人將被殺掉 被殺掉的人將從房間內被移走 然後從被殺掉的下乙個人重新報數,繼續報q,再清除,直到剩餘一人

你要做的是:當你在這一群人之間時,你必須選擇乙個位置以使得你變成那剩餘的最後一人,也就是活下來。

特例:2,當q = 2時候,是乙個特例,能快速求解

特例還分兩種

如果只有2個人,顯然剩餘的為1號

如果有4個人,第一輪除掉2,4,剩下1,3,3死,留下1

如果是8個人,先除去2,4,6,8,之後3,7,剩下1,5,除去5,又剩下1了

……定義j(n)為n個人構成的約瑟夫環最後結果,則有j(2^k) = 1

j(n) = 2^k – 2^k-1 = 2^k-1 n=2^k

j(n) = 2^k-1 – 2^k-2 = 2^k-2 n=2^k-1

………j(2^2) = 2^2 – 2^1 = 2^1 n=2^2

遞推得到如上結果,起始我們仔細分析也就是每次除去一半的元素,然後剩餘的一半繼續重複之前的策略,再除去一半。(可想到遞迴)

結合:j(2) = 1 我知道兩個數,從1開始,肯定是2先死,剩下1.

得到:j(2^k) = 1

n 不等於 2^k時,就不存在這樣的easy的規律了,重新分析:

假設n = 9,這時候如圖下:

能看出來,我們乾掉第乙個人也就是2,之後就只剩下8個人了,又回到j(2^k)上了,這時候我們需要的是找到當前的1號元素。

見圖下:

這時候,我們從3號開始,就成了另外乙個規模小1的約瑟夫問題(恰好為2^k的特例)。

這時候,我們可以把3號看成新的約瑟夫問題中的1號位置:

j(8) = j(2^3) = 1,也就是說這裡的1代表的就是上乙個問題中的3號

so:j(9) = 3

答案為3號

同理可知所有的非2^k的數都是這樣:

假設n = 2^k + t,t可以隨意取,比如1,2,3…….

假設n = 11,這時候n = 2^3 + 3,也就是說t = 3,所以開始剔除元素直到其成為2^k問題的約瑟夫問題。

so,我們在剔除了t(3)個元素之後(分別是2,4,6),此時我們定格在2t+1(7)處,並且將2t+1(7)作為新的一號,而且這時候的約瑟夫環只剩下2^3,也就是j(2^3 + 3) = 2*3 + 1 = 7,答案為7

總結一下這個規律:

j(2^k + t) = 2t+1

當q ≠ 2:

我們假定:

- n — n人構成的約瑟夫環

- q — 每次移除第q個人

約定:- jq(n)表示n人構成的約瑟夫環,每次移除第q個人的解

- n個人的編號從0開始至n-1

我們沿用之前特例的思想:能不能由jq(n+1)的問題縮小成為j(n)的問題(這裡的n是n+1規模的約瑟夫問題消除乙個元素之後的答案),jq(n)是在jq(n+1)基礎上移除乙個人之後的解。也就是說,我們能由jq(n)得到jq(n+1)。

規律:jq(n+1) = ( jq(n) + q ) / (n+1)

詳細推導過程見這篇博文

大致是如下這樣:

0 1 2 3 4 5 ...... n-1 總共n人

設第q個人也就是下標為q-1的那位,殺死:

剩下n-1個人,如下:

q q+1 q+2 ...... n-2 n-1 0 1 2 ...... q-2 (這裡是除去q-1這位兄台的剩餘n-1人)

這時,又來重複我們的老套路:將新的被殺的後乙個人作為新的0號,於是新的如下:

0 1 2 ...... .......... ........ n-2

其實就是從q開始,到之前最大數n-1,每個數都減去q,從0開始之後接著n-1這個新的值每次往後加1,直到加到n-1(這個下標)

舉個例子:

j4(9) :

0 1 2 3 4 5 6 7 8 消去3--> 0 1 2 4 5 6 7 8( 0 1 2)

對應的新值: 0 1 2 3 4 5 6 7

其中:q=4,從3之後第乙個數4開始:每個數5-q=1,6-q=2,7-q=3,8-q=4,因為是個環,0-q=-4,1-q=-3 ....直到加到n-1=7

這就相當於乙個限定範圍內的數的相對位置,-1代表的是最後乙個元素,也就是之前的8

(-2就代表7,-3代表6,-4代表5.....-9代表0,從後面開始數過來第9位)

大致過程如圖下:

那麼我們知道是這麼得到的新的佇列,那麼也很容易知道怎麼反推了:

反觀如上的變化情況,都是減去乙個q,所以:

變回去的公式如下:old = (new + q) % n

這裡的old和new指的是下標,n指的是總共有多少人

知道了怎麼推出之前的下標,那麼也就可以一步步遞推回去得到開始的佇列或者從小推到大得到最後剩餘的結果。

j2(1) = 0

j2(2) = (j2(1) + 2) / 2 = 0

j2(3) = (j2(2) + 2) / 3 = 2

j2(4) = (j2(3) + 2) / 4 = 0

……..

這樣一步步求就能得到所有的給出n和q條件的答案了。

#include

#include

using namespace std;

int yuesefu(int n,int m)

else

}int main(void){

int a,b;

cin>>a>>b;

cout<

在遇上包含特殊的出隊規則相關的題目時,應該聯想到是否是約瑟夫環問題,方便求解。

基本約瑟夫環問題詳解

本人水平有限,題解不到為處,請多多諒解 本蒟蒻謝謝大家 推薦部落格 傳送門 首先讓我們來看一下這一段 n 2 k1 n 2 n1 n1為當前序列的總人數,因為是迴圈的序列,k1 n 1可能大於總人數 至關重要,比如 我們已經知道當前的最後乙個出列的位置為f 設下一次最後乙個出列的位置為ans 則an...

C 約瑟夫環問題詳解

有一家公司,這個公司有一位老闆和13名程式設計師,每天下班前老闆都會組織他們玩一次遊戲,遊戲的勝利者可以不加班,失敗者需要加班2小時。遊戲規則如下 一張圓桌共有13個座位,從1到13編號,遊戲開始前老闆會說出今天開始報數的座位編號start和淘汰序號k。然後13名程式設計師開始搶位置,每個位置只能容...

約瑟夫問題 約瑟夫環

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