约瑟夫问题小结

前前后后做过三道关于约瑟夫问题的题了。然而今天这次考试让我认识到其实我并没有完全理解约瑟夫问题的解法。

今天花了大概一个多小时的时间彻底弄明白了(可能是我太垃圾,用的时间还是太长了),以后如果再考约瑟夫应该不会挂了吧。。。

约瑟夫游戏(题目大意:经典约瑟夫问题,要求输出出圈顺序,数据范围$30000$)

这道题目是初学OI那段时间写的??码风还没成型。$O(n^2)$暴扫即可。

约瑟夫问题二(题目大意:经典约瑟夫问题,要求输出获胜者编号,数据范围$1e8$)

我们将一个还剩下$n$个人的约瑟夫问题成为一个n阶问题。

对于一个n阶问题,我们给所有成员依次编号为$0,1,2...n-1$,

即$0$号要报$"1"$,$1$号要报$"2"$,以此类推,本轮游戏的出局者一定是编号为$(m-1)%n$的人。

从$n$阶问题到$n-1$阶问题,部分人的编号将发生改变。根据命名规则,编号为$(m-1)%n+1$的人将被命名为$0$。

此时设第$i$个人在$n-1$阶问题中的编号为$f_i$,在n阶问题中的编号为$g_i$,则可由$f_i$推得$g_i$:$g_i=(f_i+m)%n$。

解释:如右图:对于每一阶问题中,一个人的编号还可以表示在他前面报数的人数。对于$n-1$阶问题,$i$的前面有$f_i$个人。本阶问题的$0$号在上一阶问题中一定在出局者后面。我们假设$n$足够大。则本阶的$0$号在上一阶前面一定有$m$个人。此时,$g_i=(f_i+m)%n$。模$n$意义下同理。

此时我们得到了由$n-1$阶问题推向$n$阶问题的一般公式。而我们还知道,在第1阶问题的幸存者必定被编号为$0$。于是我们就可以$O(n)$推导出这名幸存者在第一轮,即第$n$阶问题中的编号是多少,此时即为所求答案。

One(题目大意:约瑟夫问题改编版:第i轮报"i"者出局,求获胜者编号,数据范围$1e7$)

第i轮报"i"者出局,将式子$g_i=(f_i+m)$中的$m$替换为$n-i+1$即可。

嘟嘟噜(题目大意:经典约瑟夫问题,数据范围$n \leqslant 1e9,m \leqslant 1e5$)

数据范围$1e9$,$O(n)$递推会$T$掉。考虑加速我们刚才的过程。观察数据范围可以发现,$m$远小于$n$。

此时的倒序推导过程可以跳步实现。对于一个$i$阶问题,$i$远大于$m$时,可以直接跳到第$i+k$轮求解。

$k=min((i-1-ans)/m+1,n-i+1)$(在这个式子中我们取剩下$i-1$个人为第i轮翻转)

解释:$i-1$为边界。(这里我们没有必要预估跳了$k$步后的边界。对于当前边界求解即可。)$ans$为当前幸存者的编号。

$i-1-ans$是边界到$ans$的距离,除以m即为出局位置移动到边界所需步数。$+1$为翻过边界进入下一层的那一步。

$i$也是轮数,$n-i+1$为我还需要的轮数。(肯定不能还原到$n+1$个人的时候吧……)

时间复杂度……大概接近$O(m)$??

原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11624733.html

时间: 2024-08-30 11:40:59

约瑟夫问题小结的相关文章

约瑟夫环小结(线段树)

题目大意: 输入初始人数编号为1~n,以及初始密码m,输出出局序列. 解法一:用线段树可解. Segtree节点存储左右区间和该区间下包含的人数. void Build(int p,int left,int right)表示从编号为p,区间为[l,r]的节点开始向下建树. int Update(int p,int id)表示从编号为p的节点开始查询在新队伍中编号为id的人出局,返回该人在最初队伍中的编号. 而temp=(temp+m-1)%seg[1].manum;语句用于求出下一个出局的人在新

约瑟夫问题例题小结

类型1:约瑟夫问题原题:(http://acm.hdu.edu.cn/showproblem.php?pid=2925) 大体就是一圈人,数到m的退出,询问最后留下来的人. 这样的题是约瑟夫系列问题的基础,普通暴力做法O(n*m),不够优秀,可以通过数学方法优化至O(n),其所用的思路是将一个规模n的问题转移成规模n-1的问题. 公式形式推导都很简单:f(i)表示规模i的约瑟夫问题最后留下人的编号,f(i)=(f(i-1)+m)%i 类型2:规模变态版:(http://poj.org/probl

约瑟夫环问题小结

一 问题描述 约瑟夫环问题的基本描述如下:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为1的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,要求找到最后一个出列的人或者模拟这个过程. 二 问题解法 在解决这个问题之前,首先我们对人物进行虚拟编号,即相当于从0开始把人物重新进行编号,即用0,1,2,3,...n-1来表示人物的编号,最后返回的编号结果加上1,就是原问题的解(为什么这么做呢,下文有解释).而关于该问题的解

一个不简洁的约瑟夫环解法

约瑟夫环类似模型:已知有n个人,每次间隔k个人剔除一个,求最后一个剩余的. 此解法为变种,k最初为k-2,之后每次都加1. 例:n=5,k=3.从1开始,第一次间隔k-2=1,将3剔除,第二次间隔k-1=2,将1剔除.依此类推,直至剩余最后一个元素. 核心思路:将原列表复制多份横向展开,每次根据间隔获取被剔除的元素,同时将此元素存入一个剔除列表中.若被剔除元素不存在于剔除列表,则将其加入,若已存在,则顺势后移至从未加入剔除列表的元素,并将其加入.如此重复n-1次.面试遇到的题,当时只写了思路,没

使用Apache POI导出Excel小结--导出XLS格式文档

使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI导出Excel小结--导出XLSX格式文档 使用Apache POI导出Excel--大数量导出 导出XLS格式文档 做企业应用项目难免会有数据导出到Excel的需求,最近在使用其,并对导出Excel封装成工具类开放出来供大家参考.关于Apache POI Excel基本的概念与操作我在这里就不啰嗦

【c语言】数据结构(约瑟夫生者死者游戏的问题)

约瑟夫生者死者游戏:30个旅客同乘一条船,因为严重超载,加上风高浪大,危险万分:因此船长告诉大家,只有将全船一半的旅客投入海中,其余人才能幸免遇难.无奈,大家只得同意这种办法,并议定30个人围成一圈,由第一个人开始,依次报数,数到第9个人,就把他投入大海中,然后从他的下一个人开始从1数起,数到第9个人,再将她投入大海,如此循环,直到剩下15个人乘客为止.问哪些位置是将被扔到大海的位置. 解法有许多种,可以用数组,应为涉及到删除操作,数组(顺序线性表)比较麻烦,但不必要删除,只需要给跳船的人(元素

算法系列:约瑟夫斯问题

约瑟夫斯问题(有时也称为约瑟夫斯置换),是一个出现在计算机科学和数学中的问题.在计算机编程的算法中,类似问题又称为约瑟夫环. 有{\displaystyle n}个囚犯站成一个圆圈,准备处决.首先从一个人开始,越过{\displaystyle k-2}个人(因为第一个人已经被越过),并杀掉第k个人.接着,再越过{\displaystyle k-1}个人,并杀掉第k个人.这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着. 问题是,给定了{\displaystyle n}和{

【转载】小结一下linux 2.6内核的四种IO调度算法

在LINUX 2.6中,有四种关于IO的调度算法,下面综合小结一下: 1) NOOP NOOP算法的全写为No Operation.该算法实现了最最简单的FIFO队列,所有IO请求大致按照先来后到的顺序进行操作.之所以说“大致”,原因是NOOP在FIFO的基础上还做了相邻IO请求的合并,并不是完完全全按照先进先出的规则满足IO请求.NOOP假定I/O请求由驱动程序或者设备做了优化或者重排了顺序(就像一个智能控制器完成的工作那样).在有些SAN环境下,这个选择可能是最好选择.Noop 对于 IO

Android基础入门教程——8.1.3 Android中的13种Drawable小结 Part 3

Android基础入门教程--8.1.3 Android中的13种Drawable小结 Part 3 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来把剩下的四种Drawable也学完,他们分别是: LayerDrawable,TransitionDrawable,LevelListDrawable和StateListDrawable, 依旧贴下13种Drawable的导图: 1.LayerDrawable 层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来