约瑟夫环问题
来源:互联网 发布:淘宝今日销量 编辑:程序博客网 时间:2024/05/01 08:14
约瑟夫环问题
问题描述:
n个人围成一个圆圈依次编号为0,1,…,n-1,从第一个人开始,依次报数1, 2,…,k-1,报到k的人退出,从退出的下一个人开始继续从1报数,仍然报到k的人退出,问最后留下的人是谁。
朴素解法:
这是一个c语言入门题,我们可以用数组或者链表来模拟整个过程得到最终结果。但是这样复杂度为O(n^2),当n较大时没法算出结果。
数学解法:
先来模拟一下过程,当n = 8,k = 3时
n = 8, k = 3
0 1 2 3 4 5 6 7
第一次编号为2的退出n = 7, k = 3
0 1 3 4 5 6 7
这次将从3开始数,从新进行编号
3 4 5 6 7 0 1 (A)
0 1 2 3 4 5 6 (B)
可以发现从(B)式到(A)式有(A) = ((B) + k)%(n+1)
可以继续模拟下去,可以发现这个公式始终满足,显然我们知道当n==1的时候,最后留下的肯定为0,所以我们可以根据这个公式自底向上的计算下去了。
代码:
递归版本:
int fun(int n, int k) { if(n == 1) return 0 else return (fun(n - 1, k) + k) % n;}
循环版本:
const int maxn = 1000;int f[maxn];int fun(int n, int k) { f[0] = 1; for(int i = 0; i < n; i++) { f[i] = (f[i-1] + k) % n; }}
很明显当有多次查询的时候,使用循环版本把答案一次算完可以避免重复计算,当然递归版本记忆化也是可以的。
拓展:
当然朴素的约瑟夫环肯定是一个送分题,这周bc就有一个简单拓展题目
King’s Game 为了铭记历史,国王准备在阅兵的间隙玩约瑟夫游戏。它召来了 n(1\le n\le 5000)n(1≤n≤5000) 个士兵,逆时针围成一个圈,依次标号 1, 2, 3 ... n1,2,3...n。
第一轮第一个人从 11 开始报数,报到 11 就停止且报到 11 的这个人出局。
第二轮从上一轮出局的人的下一个人开始从 11 报数,报到 22 就停止且报到 22 的这个人出局。
第三轮从上一轮出局的人的下一个人开始从 11 报数,报到 33 就停止且报到 33 的这个人出局。
第 n - 1n−1 轮从上一轮出局的人的下一个人开始从 11 报数,报到 n - 1n−1 就停止且报到 n - 1n−1 的这个人出局。
最后剩余的人是幸存者,请问这个人的标号是多少?
如果理解朴素的约瑟夫环话,可以发现这里就是一个简单的递推变化,同样定义
int f(int n, int k) { if(n == 1) return 0; else return (f(n - 1, k + 1) + k) % n;}
复杂度O(n)
- 约瑟夫问题、约瑟夫环
- Josephus约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题(Josephus)
- 约瑟夫环问题--java
- 约瑟夫环问题 Josephus
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 求解约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 约瑟夫环问题
- 杭电oj 2011 多项式求和
- 编程是一门艺术
- opencv haartraining训练过程总结dir /b > info.txt
- 开启一个线程
- JS第一章
- 约瑟夫环问题
- JavaScript事件
- 面试中的 10 大排序算法总结
- MySQL数据库总结(4)子查询与联合
- 第三周项目1个人所得税计算器
- 198. House Robber
- JavaScript全排列的六种算法 具体实现
- 搭建PHP环境需要安装Apache服务器,遇到的一系列的问题(切记需要用管理权限进入CMD)
- redhat6.4配置yum