本文系转载,权侵删.

基本问题描述:

已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为1的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。(也类似于变态杀人狂问题)通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。通常,我们会要求输出最后一位出列的人的序号。那么这里主要研究的是最后一个出列的人的序号要怎么确定。

当n,m数据量很小的时候,我们可以用循环链表模拟约瑟夫环的过程。当模拟到人数等于1的时候,输出剩下的人的序号即可。
具体解法这种方法往往实现起来比较简单,而且也很容易理解。但是时间复杂度却是很糟糕的,达到了O(nm),这样的话,其实在n,m比较大的时候(nm达到10^8或者更大),那么要得出结果往往需要耗费很长的时间,但是我们可以运用一点数学上的技巧,将最后结果推导出来。

为了简化出列的过程:
首先我们把这n个人的序号编号从0~n-1(理由很简单,由于m是可能大于n的,而当m大于等于n时,那么第一个出列的人编号是m%n,而m%n是可能等于0的,这样编号的话能够简化后续出列的过程),当数到m-1的那个人出列,因此我们编号完成之后,开始分析出列的过程:
第一次出列:
一开始的时候,所有人的编号排成序列的模式即为:
0,1,2,3,4,5...n-2,n-1
那么第一次出列的人的编号则是(m-1)%n1,那么在第一个人出列之后,从他的下一个人又开始从0开始报数,为了方便我们设k1 = m%n1(n1为当前序列的总人数)那么在第一个人出列之后,k1则是下一次新的编号序列的首位元素,那么我们得到的新的编号序列为:
k1,k1+1,k1+2,k1+3...n-2,n-1,0,1,2...k1-3,k1-2 (k1-1第一次已出列)
那么在这个新的序列中,第一个人依旧是从0开始报数,那么在这个新的序列中,每个人报的相应数字为:
0,1,2,3....n-2
那么第二次每个人报的相应数字与第一次时自己相应的编号对应起来的关系则为:
0 --> k1
1 --> k1+1
2 --> k1+2
...
n-2 ---> (k1+n-2)%n1(n1为当前序列的总人数,因为是循环的序列,k1+n-1可能大于总人数)
那么这时我们要解决的问题就是n-1个人的报数问题(即n-1阶约瑟夫环的问题)
可能以上过程你还是觉得不太清晰,那么我们重复以上过程,继续推导剩余的n-1个人的约瑟夫环的问题:
那么在这剩下的n-1个人中,我们也可以为了方便,将这n-1个人编号为:
0,1,2,3,4...n-2
那么此时出列的人的编号则是(m-1) % n2(n2为当前序列的总人数),同样的我们设k2 = m % n2,那么在这个人出列了以后,序列重排,重排后新的编号序列为:
k2,k2+1,k2+2,k2+3...n-2,n-1,0,1,2...k2-3,k2-2 (k2-1第一次已出列)
那么在这个新的序列中,第一个人依旧是从1开始报数,那么在这个新的序列中,每个人报的相应数字为:
1,2,3,4....n-2
那么这样的话是不是又把问题转化成了n-2阶约瑟夫环的问题呢?
后面的过程与前两次的过程一模一样,那么递归处理下去,直到最后只剩下一个人的时候,便可以直接得出结果
当我们得到一个人的时候(即一阶约瑟夫环问题)的结果,那么我们是否能通过一阶约瑟夫环问题的结果,推导出二阶约瑟夫环的结果呢?
借助上面的分析过程,我们知道,当在解决n阶约瑟夫环问题时,序号为k1的人出列后,剩下的n-1个人又重新组成了一个n-1阶的约瑟夫环,那么
假如得到了这个n-1阶约瑟夫环问题的结果为ans(即最后一个出列的人编号为ans),那么我们通过上述分析过程,可以知道,n阶约瑟夫环的结果
(ans + k)%n(n为当前序列的总人数),而k = m%n
则有:
n阶约瑟夫环的结果

(ans + m % n)%n,那么我们还可以将该式进行一下简单的化简:

当m=n时,那么上式则化简为:(ans % n + m%n%n)% n
即为:(ans % n + m%n)% n
而 (ans + m)% n = (ans % n + m%n)% n
因此得证
(ans + m % n)%n = (ans + m)% n
这样的话,我们就得到了递推公式,由于编号是从0开始的,那么我们可以令
f[1] = 0; //当一个人的时候,出队人员编号为0
f[n] = (f[n-1] + m)%n //m表示每次数到该数的人出列,n表示当前序列的总人数
而我们只需要得到第n次出列的结果即可,那么不需要另外声明数组保存数据,只需要直接一个for循环求得n阶约瑟夫环问题的结果即可

由于往往现实生活中编号是从1-n,那么我们把最后的结果加1即可。

#include <stdio.h>
int main()
{int n, m, i, s = 0;printf ("N M = ");scanf("%d%d", &n, &m);for (i = 2; i <= n; i++){s = (s + m) % i;printf("%d\n",s);}printf ("\nThe winner is %d\n", s+1);
}

约瑟夫环问题(用数学方法推出计算公式)相关推荐

  1. 约瑟夫环问题(数学方法)

    问题描述: 约瑟夫环问题(Josephus) 用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出.写出C程序. 解法一: 思路:建立一个有N个元素的循环链表,然后从链表表头遍 ...

  2. 约瑟夫环问题(数学递推法)

    约瑟夫环问题起源于一个犹太故事: 罗马人攻占了桥塔帕特,41个人藏在一个山洞中躲过了这场浩劫.这41个人中,包括历史学家Josephus(约瑟夫)和他的一个朋友.剩余的39个人为了表示不向罗马人屈服, ...

  3. 循环链表解决约瑟夫环问题

    约瑟夫环问题可以简单的使用数组的方式实现,但是现在我使用循环链表的方法来实现,因为上午看到一道面试题规定使用循环链表解决约瑟夫环问题. 什么是约瑟夫环? "约瑟夫环是一个数学的应用问题:已知 ...

  4. 约瑟夫环之循环链表实现

    约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开 始报数,数到m的那个人又出列:依此规律 ...

  5. java实现简单的约瑟夫环问题

    我自己学习数据结构的时候,总希望能找到很简单的入门代码,可总是很难找到,于是就想到能写一些简单的java代码.  在百度百科上面搜索到约瑟夫环的问题时,并没有发现java的简单实现,自己在下面弄也是弄 ...

  6. python约瑟夫环算法和流程图_约瑟夫环问题及python与c++实现效率对比

    约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重 ...

  7. python约瑟夫环问题_约瑟夫环问题的Python实现

    约瑟夫斯问题(有时也称为约瑟夫斯置换),是一个出现在计算机科学和数学中的问题.在计算机编程的算法中,类似问题又称为约瑟夫环. 有 个囚犯站成一个圆圈,准备处决.首先从一个人开始,越过 个人(因为第一个 ...

  8. 7-1 约瑟夫环问题-hebust (10 分)

    7-1 约瑟夫环问题-hebust (10 分) 约瑟夫环问题 约瑟夫环是一个数学的应用问题:已知n个人(以编号a,b,c-分别表示)围坐在一张圆桌周围.从编号为1的人开始报数,数到m的那个人出列:他 ...

  9. 约瑟夫环问题(C语言数组和循环链表)

    本文将用两种方式(数组和循环链表)求解约瑟夫环问题,为了更好理解,本文将从洛谷的P1996 约瑟夫问题出发. 题目描述 n个人围成一圈,从第一个人开始报数,数到 m的人出列,再由下一个人重新从1开始报 ...

最新文章

  1. Hive Metastore 连接报错
  2. CentOS-文件操作
  3. OpenCV实现图像对齐ECC算法(附完整代码)
  4. 史上最全的CSS hack方式一览
  5. numpy之高维数组的转置:transpose方法——通过几何体来迅速理解
  6. 算法—递归实现 C(m,n)
  7. jsp+javabean实现购物车
  8. ubuntu的两种网络连接模式
  9. 编程通用知识 字符编码(ascii,unicode,utf-8)
  10. 数组作为方法的返回值
  11. 2.性能之巅 洞悉系统、企业与云计算 --- 方法
  12. eclipse快速导包快捷键_【IntelliJ IDEA mac新手入门】IDEA如何快速搭建Java开发环境...
  13. BIOS的两种引导模式
  14. python scipy.optimize 非线性规划 求解局部最优和全局最优
  15. 行人三维姿态与形状估计面试准备
  16. python壁纸程序代码_40行Python代码+奇技淫巧搞定专属电脑壁纸库
  17. torch.utils.data.WeightedRandomSampler样本不均衡情况下带权重随机采样
  18. MDClub(开源社区系统) v1.0.0
  19. openjudge 海贼王之伟大航路(状压dp)
  20. 打豆豆游戏c语言编程,C语言程序打豆豆(函数版)分享!

热门文章

  1. 【G4基础08】GPS-2-Macro Commands宏命令
  2. 公司到底想要什么样的人?
  3. C语言if选择练习题
  4. Origin 在已画图中添加新的数据曲线
  5. 附近商家位置java开发附近定位
  6. 气象学需要计算机知识吗,应用气象学专业学什么
  7. 二十六个英语字母相关的公司商标
  8. k8s开启IPVS模式
  9. Unity实现轻量化答题软件,随机题库,非SQL数据库加载形式
  10. 【matlab】雷达截面积(Radar Cross Section,RCS)(MATLAB部分仿真+Code)