猴子选大王
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;
}
Sample Input
6 5 9
3 3 11
Sample Output
3
3
#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;
}