關於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:

#include<iostream>
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;
}
當然也可通過設變數為字母找到此規律-.-;