總共有 n 個人編號為 1 號到 n 號(每個人的編號一直不變),一開始只取 1 號到 m 號沿順時針圍成一圈(臉都對著圓心)。同樣是依次報數,當輪到報數為 k 的人時,如果此人的編號為奇數,則將剩餘的人中編號最小的人插入此人右側,如果此人的編號為偶數,則將剩餘的人中編號最小的人插入此人左側。並從報數為 k 的人左側開始重新開始重複此過程。當圍成乙個 n 個人的圈後,繼續從報數為 k 的人左側重新開始沿順時針報數,當有人再次報數為 k 時,此人出列。繼續從出列的人的左側重新開始重複此過程。直到圍成圈的人數再次為 m 時停止。
問: 最後留下的 m 個人中,有多少來自一開始取的 m 個人。
注: 鍊錶中當 n 非常大時,考慮到時間複雜度,k 可以取 k≪n。
示例: 假設 n=6, m=4, k=2。則一開始取的人編號分別 1,2,3,4 的人圍成一圈。然後從 1 開始報兩個數。 2 為偶數,則圓圈中編號為 2 的人左側位置加乙個 5,圓圈的順序變為: 1,2,5,3,4。 又從 5 開始重新報數,報 2 的人為 3 號,則往其圓圈中的右側位置加乙個 6。圓圈順序變為 1,2,5,6,3,4。 此時 6 人全部在圓圈中,繼續從剛剛的 3 號的下一位 4 號報數,報 2 的人為 1 號,則 1 號出列。圓圈順序變為 2,5,6,3,4,繼續從 1 號下一位開始報數,下一次報 2 的為 5 號,則 5 號出列。則圓圈的順序變為 2,6,3,4。其中 2,3,4 號來自於一開始取的 1,2,3,4 中,所以答案為 3。
按照 n m k 的順序輸入引數,其中 n 為總人數,m 為初始的選取人數,k 是每次報數的個數。
輸出最後剩餘 m 人中屬於最開始 m 人的個數
6 4 2
一道簡單的迴圈鍊錶應用題,注意處理好新增表頭時指標的判斷。
#include
using namespace std;
struct node;
struct list;
void initlist(list &l)
void einsert(node *&p,node *&
q,int i)
void oinsert(node *&p,node *&
q,int i)
int main()
node *p=circle.head,*q=circle.head->next;
for(int i=m+1;i<=n;i++)
p=q;
q=p->next;
if(q==circle.head)
}if(q->num % 2==0)
einsert(p,q,i);
else
oinsert(p,q,i);
}if(q==circle.head)
for(int i=n;i>m;i--)
}p->next=q->next;
delete
q; q=p->next;
if(q==circle.head)
}node *seek=circle.head->next;
int remain=0;
while(seek!=circle.head)
coutcout0;}
約瑟夫問題 約瑟夫環
約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...
約瑟夫問題 約瑟夫環
約瑟夫問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死也...
約瑟夫問題
這是17世紀的法國數學家加斯帕在 數目的遊戲問題 中講的乙個故事 15個教徒和15 個非教徒在深海上遇險,必須將一半的人投入海中,其餘的人才能倖免於難,於是想了乙個辦法 30個人圍成一圓圈,從第乙個人開始依次報數,每數到第九個人就將他扔入大海,如此迴圈進行直到僅餘15個人為止。問怎樣排法,才能使每次...