約瑟夫環問題描述: n
個人圍成一圈(編號分別為1-n),從某人開始順序報號1,2,3…m凡報到m者的人出列,再接著從下乙個人開始數,輸出最終出列的人的編號。
(約瑟夫環是乙個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下乙個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。)
輸入總人數n,接著輸入乙個整數k和m,前者表示從第k人開始數,後者表示每次數到m的人出列,(n,k,m之間均用空格隔開, 1 <= k <= n <= 10000)
sample input
5 2 3
7 1 3
sample output54
上述方法的效率很低,其時間複雜度為o(mn)。當n和m很大時,很難在短時間內得出結果。不過好處就是可以給出n個人出圈的次序。只要在刪除前儲存一下即可。
下面利用數學推導,如果能得出乙個通式,就可以利用遞迴、迴圈等手段解決。下面給出推導的過程:
(1)第乙個被刪除的數為 (m - 1) % n。
(2)假設第二輪的開始數字為k,那麼這n - 1個數構成的約瑟夫環為k, k + 1, k + 2, k +3, .....,k - 3, k - 2。做乙個簡單的對映。
k -----> 0
k+1 ------> 1
k+2 ------> 2
...
...
k-2 ------> n-2
這是乙個n -1個人的問題,如果能從n - 1個人問題的解推出 n 個人問題的解,從而得到乙個遞推公式,那麼問題就解決了。假如我們已經知道了n -1個人時,最後勝利者的編號為x,利用對映關係逆推,就可以得出n個人時,勝利者的編號為 (x + k) % n。其中k等於m % n。代入(x + k) % n <=> (x + (m % n))%n <=> (x%n + (m%n)%n)%n <=> (x%n+m%n)%n <=> (x+m)%n
(3)第二個被刪除的數為(m - 1) % (n - 1)。
(4)假設第三輪的開始數字為o,那麼這n - 2個數構成的約瑟夫環為o, o + 1, o + 2,......o - 3, o - 2.。繼續做對映。
o -----> 0
o+1 ------> 1
o+2 ------> 2
...
...
o-2 ------> n-3
這是乙個n - 2個人的問題。假設最後的勝利者為y,那麼n -1個人時,勝利者為 (y + o) % (n -1 ),其中o等於m % (n -1 )。代入可得 (y+m) % (n-1)
要得到n - 1個人問題的解,只需得到n - 2個人問題的解,倒推下去。只有乙個人時,勝利者就是編號0。下面給出遞推式:
f [1] = 0;
f [ i ] = ( f [i -1] + m) % i; (i>1)
第二種方法:根據以上推出的結論
ac**:
#include
using namespace std;
int solution(int n, int m)
int main(void)
{int n,m,t;//n表示總人數,m表示間隔人數,t表示起始人的序號
cin>>n>>m>>t;
cout<<(solution(n,m)+t-1)%n+1<
約瑟夫問題 約瑟夫環
約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...
約瑟夫問題 約瑟夫環
約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...
數論三 約瑟夫問題
描述 小hi和小ho的班級正在進行班長的選舉,他們決定通過一種特殊的方式來選擇班長。首先n個候選人圍成乙個圈,依次編號為0.n 1。然後隨機抽選乙個數k,並0號候選人開始按從1到k的順序依次報數,n 1號候選人報數之後,又再次從0開始。當有人報到k時,這個人被淘汰,從圈裡出去。下乙個人從1開始重新報...