自然语言解释:约瑟夫环之递归算法

#include <iostream>
using  namespace  std;
const  int  m = 3;
int  main()
{
     int  n, f = 0;
     cin >> n;
     for  ( int  i = 1; i <= n; i++) f = (f + m) % i;
     cout << f + 1 << endl;
}


---------------------------------------------------------------------------
作者:葛溪驿
链接:https://www.zhihu.com/question/20065611/answer/78681758
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

》》当有n个人的时候,他们的编号依次是0、1、2、3、4、………、n-1。假设最后编号为x(n)的人会留下来。
》》因为数到m的那个人会出列,那么此轮中编号为(m-1)%n的人会出列,编号为(m+0)%n的人将做为下一轮编号为0的人,此轮编号为(m+i)%n的人将做为下一轮编号为i的人…
》》因此当有n-1个人的时候,编号为i的人对应着上一轮编号为(m+i)%n的人。假设此轮编号为x(n-1)的人最终会留下来。因为编号为x(n-1)的人肯定对应着上一轮的x(n),所以有x(n)=(m+x(n-1))%n
》》有了这个递推公式,那我们就可以一直递推到x(2)=(m+x(1))%2,而x(1)=0。
》》所以我们可以这么来写这个函数:
》》j = 0
》》for i 从 2 到 n:
》》》》j = (m+j)%i
》》最终第j个人会留下来(如果从1开始编号就是第j+1个人最终会留下来)。



》》比如当m=5,n=5时。这5个人的编号依次是:0、1、2、3、4。第一轮中报数m的人是4号,他的编号可以通过(m-1)%n算出来。
》》第二轮中将以第一轮编号为(m%n=)0的人做为新的编号为0的人。此轮中编号为0、1、2、3的人对应着上一轮中编号为0、1、2、3的人。
》》关键点来了,假设最后留下来的人的在第一轮中编号为x(5),在第二轮中编号为x(4)。那么由两轮的对应关系可以得到 x(5) = (m+x(4))%n。
》》也就是说x(5) =(5+x(4))%5
》》同样有x(4) =(5+x(3))%4
》》……得到递推关系式: x(i) = (m+x(i-1))%i
》》那么要求x(i)的话必须要知道x(i-1)。而已经知道当有1个人的话留下来话,这个人的编号肯定是0,就是x(1) = 0。
》》现在先让j=0,
》》然后让i 从2遍历到n
每一次遍历给j赋一个递推的新值:
》》》》j=(m+j)%i
》》循环完后j就是有n个人时最后会留下来的人的编号。答案就是j了
》》如果要编号为1开始的话就输出j+1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值