Josephu问题的数学解法

今天重新做了次Josephu问题,之前做的是使用链表来实现的,直接模拟了整个过程,这次使用了数学解法。

Josephu问题:编号为0到N-1的N个人围成一圈,然后从1开始报数,报到M的那个人被杀掉,剩下的人接着从1开始报数,求最后的幸存者编号。

首先对于对于第一轮:

0, 1, 2, ......, M-2, M-1, M, M+1, ......N-2, N-1 ---------------------------------数组1 (N个人)

剩下的人:

0, 1, 2, ......, M-2, M, M+1, ......, N-2, N-1

对剩下的人的排列换成下面这样:

M, M+1, M+2, ......, N-2, N-1, 0, 1, 2, ......, M-2 --------------------------------数组2 (N-1个人)

很容易发现上面的数组2等价于:

 {(x+M)mod N | x = 0, 1, 2, ......, n-3, n-2} ------------------------------------数组3;

很明显如果知道了数组2 中幸存者编号,那也等于知道了数组1中幸存者的编号;

而数组2 等价于数组3,所以现在问题变成了从 0到 n-2 的人中找幸存者;即假设我们从0到 n-2 中找到了幸存者编号为x,那么根据公式 (x + M)mod N 即可得到数组2 中的幸存者编号,也即数组1 N个人中的幸存者。

到此这个问题就是就可以总结为,如果知道了N-1个人中幸存者的编号,则可计算出N个人中幸存者的编号;

N应该大于等于1,而当N=1时,只有一个人,那编号就是0;代码如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. int josephu(int n, int m);  
  5.   
  6. int main(int argc, char **argv)  
  7. {  
  8.     int n, m;  
  9.   
  10.     printf("please input N and M: ");  
  11.     scanf("%d%d", &n, &m);  
  12.     printf("result: %d\n", josephu(n, m));  
  13.   
  14.     return 0;  
  15. }  
  16.   
  17. int josephu(int n, int m)  
  18. {  
  19.     int ret = 0, i;  
  20.   
  21.     for (i = 2; i <= n; i ++)  
  22.         ret = (ret+m) % i;  
  23.     return ret;  
  24. }  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值