报数(约瑟夫环问题)

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;  
}  


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值