猴子选大王(约瑟夫环的使用,第一个不是报数人)

猴子选大王


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


首先是对题目的分析:
一看就是约瑟夫环问题(具体参考我的另一篇博客 http://blog.csdn.net/double2hao/article/details/48915157),但是与我们所学习的从第一个人开始报数的问题又有所不同,那么要如何解决这个问题呢?

此处最大的错误就是直接用报数人的编号赋予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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值