1. 程式人生 > >猴子選大王(約瑟夫環的使用,第一個不是報數人)

猴子選大王(約瑟夫環的使用,第一個不是報數人)

猴子選大王

Description

n只猴子要選大王,選舉方法如下:所有猴子按 1,2 ……… n 編號並按照順序圍成一圈,從第 k 個猴子起,由1開始報數,報到m時,該猴子就跳出圈外,下一隻猴子再次由1開始報數,如此迴圈,直到圈內剩下一隻猴子時,這隻猴子就是大王。



Input

猴子總數n,起始報數的猴子編號k,出局數字m。(2=<n<=30,k<=n)

Output

猴子大王的編號。

Sample Input 

6 5 9

3 3 11


Sample Output

3 3
首先是對題目的分析: 此處最大的錯誤就是直接用報數人的編號賦予s初始值,為什麼不可以呢?因為s是由公式推匯出的i-1個迴圈所出佇列的人的編號,與直接報數人的編號毫無關係。
(本人由於比較急於求成,在此處花了比較多的時間去糾結。) 那麼如何做呢?其實很簡單,將所有報數的人放在一條直線上看,報數人的編號的變化量其實與最終留下的人的編號的變化量是一樣的。什麼意思呢?打個比方,最初報數的人是1號,最終留下的人的編號是2號,那麼將最初報數的人的編號改為3號時,最終留下的人的編號即為3-1+2=4號。 如此來說便很簡單了,只需要考慮到k+s(此處s是第一個人報數,得到的最終結果)是否會超出n便可以了,於是在原來的結果後面添上s=(k-1+s)%n。(由於計算的時候是當做從0開始報數的,所以k需要減1) 原始碼:
#include <iostream>
using namespace std;

int main()
{
  int k,n,m,s=0;
  while(cin>>n>>k>>m)
    {
        for(int i=2;i<=n;i++)
            {
                s=(s+m)%i;
            }

            s=(s+k-1)%n;
            cout<<s+1<<endl;
        }

        return 0;
}