# include & ltiostream & gt
使用?STD::CIN;
使用?STD::cout;
int?主()
{
int?n,m;
cout & lt& lt“請輸入n=?”;
CIN & gt;& gtn;
如果(n & lt1)
{
cout & lt& lt" n必須大於1!\ n請重新輸入n=?;
CIN & gt;& gtn;
}
cout & lt& lt“請輸入m=?”;
CIN & gt;& gtm;
布爾?*?答?=?新的?布爾?[n+1];
a[0]=假;
for(int?I = 1;我& ltn+1;i++)
a[I]=真;
int?x,k = n;x = I = 0;//i是每個周期的計數變量,X是人員序號,K是剩余人數。
而(k!=0)
{
x++;
if(x & gt;n)?x = 1;//當person到達數組末尾時,序列號被重置為1。
if(a[x])i++;?//?跳過已經退出的人。
如果(i==m)
{ a[x]= false;I = 0;k-;}//計數到m時,退出人數設置為false,剩余人數減1,I設置為0,重新計數。
}
cout & lt& lt“留下來的人的序列號是:?”& lt& ltx & lt& lt”\ n”;
刪除?[]?a;
CIN . get();
CIN . get();//等待下壹次擊鍵關閉窗口。
回歸?0;
}
方法2(遞歸方法):
這個問題可以用數學方法解決。
有n人(編號為0~(n-1)),從0開始計數,報(m-1)時退出,其余繼續從0開始計數(數學求解時要註意從0開始編號,因為余數會得到0解。)
本質上是壹種遞歸,N中留守人員的序號和n-1中留守人員的序號之間存在遞歸關系。
假設第k個人被移除,那麽
0,1,2,3, ...,k-2,k-1,k,...,n-1//原始序列(1)
0, 1, 2, 3, ...,k-2,?,k,...,n-1?//去掉第k個人,也就是去掉序號k-1的人?(2)
K,K+1,...,N-1,0,1...,K-2//從序列號K開始,報0?(3)
0, 1, ...,n-k-1,n-k,n-k+1,...,n-2?//數量轉換,此時隊列為n-1人(4)
改造後完全變成(n-1)個人號的子問題。註意,(1)和(4)是同壹個問題,區別只是人數。對比(4)和(3)不難看出,0+k=k,1+k=k+1,...(3)中“0”之後的數字,
((n-3)+k)%n=k-3,((n-2)+k)%n=k-2。對於公式(3)中' 0 '之前的數,由於小於n,也可以看作是(0+k)%n=k,(1+k)%n=k+1,?因此,可以得出這樣的規律:
設(3)中的壹個數為x’,對應的(4)中的數為x,則有:x’=(x+k)% n .
當X是最後剩下的人數時,當隊列只剩下1人時,顯然X = 0;這時候妳可以回到2人時X對應的序號,3人時X對應的序號……直到n人時X的序號,這就是妳想要的。
#包含?& ltiostream & gt
使用?命名空間?std
int?主()
{
int?n,m,f = 0;
CIN & gt;& gtn & gt& gtm;
for(int?I = 2;我& lt= n;i++)?
f =(f+m)% I;
cout & lt& ltf+1 & lt;& ltendl
}