關於jos環,使用遞推公式簡化問題和程式碼,關鍵在於找到正確的遞推公式,可使用一個例子來尋找。
(數學能力較差,只好打個表找規律了)
為方便取餘運算,將編號1---n的下標表示為0--(n-1) 舉例n=11,m=3,即11個人報數,報到3的人出列
下標 0 1 2 3 4 5 6 7 8 9 10
序號 1 2 3 4 5 6 8 9 10 11
一, 4 5 6 8 9 10 11 1 2
二, 7 8 9 10 11 1 2 4 5
三, 10 11 1 2 4 5 8
四, 2 4 5 7 8 10 11
五, 8 10 11 2 4
六, 11 2 4 8
七, 8 11 2
八, 2 8
九, 2
十, 7
推到最後可知存活者為7號(紅色標記),對應下標(此下標應為最原始所對應的)為6,(實際上無論n,m為何值最後存活的人下標均為0)。
觀察紅色標記,可發現從第一行開始,每一次7對應的下標都往前推了三位(在自己所在的那一行推);
由此從上至下7對應的下標 6->3->0->6->3->0->3->0->1->1->0;
現在要做的就是從右開始往左邊推出最原始的下標,再加一就是存活者序號;
推出過程即將當前座標向右平移三位,不難發現此時推倒時應對應上一行的人數推倒~-~;
公式: (當前下標+m)%(當前所在行對應的上一行的人數);
還以11-3為例: (0+3)%2=1--> (1+3)%3=1-->(1+3)%4=0-->(0+3)%5=3......(省略).....(3+3)%11=6;得出最終下標,加一為序號7;
程式碼rx:
using namespace std;
int jos(int n,int m)
{
int i,k=0;
for (i=2;i<=n;i++)
k=(k+m)%i;
return k+1;
}
int main()
{
int n,m;
while (cin>>n>>m)
cout<<jos(n,m)<<endl;
return 0;
}
當然也可通過設變數為字母找到此規律-.-;