C时间限制:1 毫秒 | C内存限制:3000 Kb
题目内容:
有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的
人退出圈子,问最后留下的是原来第几号的那位?
输入描述
正整数n
输出描述
直接输出结果
输入样例
10
输出样例
4
要想用到递归法就必须找到f(n)和f(n-1)之间的关系,那么约瑟夫环有没有这样一个规律关系在呢,答案是有的。
我们假设n个人,报数到m的退出,最后剩下人的编号为x。那么第一次报数后,编号为m的人退出,那么剩下的人从编号为M+1继续报数,如果我们把m+1看成1,m+2看成2,....,n看成n-m,1看成是1-m+n,2看成是2-m+n,...,m-1看成是(m-1)-m+n也就是n-1,那么这就变成了一个n-1个人报数为m的约瑟夫环的问题,而且这里最后剩下人就是原来编号为x的那个人,按前面的对应关系f(n)=(f(n-1)+m)%n,这里有个例外,就是如果x=n的话,就会出现f(n)=n,而(f(n-1)+m)%n=((n-m)+m)%n=n%n=0,所以我们把编号加点小技巧,如果n个人编号从0编到n-1,那么f(n)=(f(n-1)+m)%n成立,如果换算成1到n编号,f(n)-1=((f(n-1)-1)+m)%n,也就是f(n)=((f(n-1)-1)+m)%n+1。
有了f(n)=(f(n-1)-1+m)%n+1这个公式,另外我们知道,当n=2时,m为奇数时最后留下的是2,m为偶数时最后留下的是1,我们就可以写出递归程序了,下面是递归法的C语言程序:
#include <stdio.h>
int Joseph(int n,int m)/*计算约瑟夫环的递归函数*/
{
if(n<=1||m<=1)
return -1;
if(n==2)
{
if(m%2==0)
return 1;
else
return 2;
}
else
{
return (Joseph(n-1,m)+m-1)%n+1;
}
}
int main()
{
int n,m,x;
scanf("%d %d",&n,&m);
x=Joseph(n,m);
printf("最后一个数为:%d\n",x);
return 0;
}