題目:每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。hf作為牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的:首先,讓小朋友們圍成乙個大圈。然後,他隨機指定乙個數m,讓編號為0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中,從他的下乙個小朋友開始,繼續0...m-1報數....這樣下去....直到剩下最後乙個小朋友,可以不用表演,並且拿到牛客名貴的「名偵探柯南」典藏版(名額有限哦!!^_^)。請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)。
這道題邏輯很清晰, 難點就在於每次小朋友出列以後報數的序列和小朋友的編號相關關係就被打亂了。 打亂就會導致不好分析。 所以要解決這道題,就要想辦法對這兩個序列的關係進行矯正。
現在編號是0~n-1 ,下面以a b c d 代表每次序列變換後的標識, 設k為出列序號的下乙個序號。 k = m % n
a: 0, 1, ..., k- 1, k, k + 1, ..., n-1
首先出列乙個小朋友,題目說的編號是m-1,考慮m可能會大於n,所以它的真實編號(m - 1) % n,
b: 0, 1, .., , k-2, k, k + 1, ..., n - 1
再對b序列做乙個延長,
c1: 0, 1, ..., k-2, k, k+1, ..., n-1, n, n+1, ..., n + k - 2
取c1的k以後的序列為
c2: k, k+1,...,n-1,n,n+1,...,n+k-2.
再對c2序列減去乙個k
d:0,1,...,n-2.
通過這樣的操作我們將序號和編號進行了矯正。其實就是出列以後下乙個數字變成了起始序號, 怎麼把他們轉換成起始序號的問題。(原先是0~n-1, 出列乙個小朋友後變成了0~n-2, 從而讓這個問題可以被遞迴分解進行解決)。 現在唯一的問題就是要用邏輯**對每次出列後的序列都實現這個矯正過程。
假設d是x
d->c2 : 就是對序號進行加上乙個k值就可以了 , c2 = x + k;
c2->b : 這裡直接看c2->b也是一樣的, c2多了n, n + 1, ..., n + k - 2 ,而b多了0,1,...,k-2.所以 c2 %n = (x + k ) % n = b.
所以總結下來序列的反推公式為 (d + k) % n = b
知道了序列的反推調整後還不夠,現在要根據序列的推導來得知序列結果的推導 前提條件如下
(1)序列結果也就是當圈圈大小為1時 f[1] = 0是確定的
(2)知道了序列就知道了它的出列結果。
(3) 序列推導公式(d + k ) % n = b
序列推導怎麼關聯上序列結果的推導呢?是這樣的首先這個環最終尺寸是1,唯一的下標0就是勝出者。假設 m = 4,這個環每增加1個人進行調整。心機的小明在以這個結果為前提下每次調整後都根據這個序列推導公式去占有相應的序號。兩個人的時候小明回憶了下序列的推導公式,發現(0 + 2) % 2 = 0; 他在兩個人的時候就不動, 這樣子在報數的時候下標序號為1的人先出列, 然後小明就贏了, 在三個人的時候又根據這個公式求(0 + 1) % 3 = 1 去佔據序號1. 就這樣不停的去增加就永遠不會輸了。所以實際上序列推導公式就是序列的結果推導公式
f[n] = (f[n-1] + k) % n
約瑟夫環問題 遞迴推導
題目描述 n個數,編號為 0 1,n 1 排成乙個圓圈,從數字 0 開始,每次從這個圓圈中刪除第 m 個數,請問最後乙個剩下的數是多少?推導過程 定義乙個函式f n,m 為 n 個數中取 m 最後剩下的編號。第乙個被刪除的數是 m 1 n,記為 k 此時因為序列已經不連續,函式可以定義為f n 1,...
約瑟夫環問題數學解法
首先一開始的序列 序列1 1,2,3,4,n 2,n 1,n 此時出佇列的第乙個人,位置為k,號碼肯定是m n。這個應該沒有問題,也就是取餘操作使得陣列類似能夠有迴圈的功能。此時序列2 1,2,3,4,k 1,k 1,n 2,n 1,n 此時k出佇列,序列2中為n 1個人了。根據序列2,得到序列3 ...
看不懂Python書?真不是你的問題!
python入門從哪開始,90 以上的書上都是這樣講的 先介紹 python 的基本語法規則 list dict tuple 等資料結構,然後再介紹字串處理和正規表示式,介紹檔案等io操作.就這樣一點一點往下說。然而這種按部就班的學習方法,卻令很多程式設計師望而卻步,因為這種講解無法解決初學者普遍面...