http://acm.uestc.edu.cn/#/problem/show/525

猴子选大王

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

有m个猴子围成一圈,按顺时针编号,分别为1到m。现打算从中选出一个大王。经过协商,决定选大王的规则如下:从第一个开始顺时针报数,报到n的猴子出圈,紧接着从下一个又从1顺时针循环报数,...,如此下去,最后剩下来的就是大王。

Input

第一行是一个正整数T表示测试数据的组数。下面共有T行,每行两个整数m和n,用一个空格隔开,分别表示猴子的个数和报数n。1≤m≤100,1≤n≤200。

Output

每组数据对应有一个输出,表示大王的编号。

Sample input and output

Sample Input Sample Output
1
3 2
3

题解:赤裸的约瑟夫环。利用递推关系,有f[1] = 0,f[i] = (f[i-1] + K) % i;一个递推就完成,时间复杂度为O(n)。

代码:

 #include <iostream>

 using namespace std;

 int main(){
int n,k,T;
cin>>T;
while(T--){
while(cin>>n>>k)
{
int ans = ;
for(int i=;i<=n;i++)
ans = (ans + k) % i;
cout<<ans+<<endl;
}
}
return ;
}

下面讲解下约瑟夫环的推导:

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

模拟算法很简单,这里说下数学递推算法。

先总结一下约瑟夫环的递推公式:

  1. f[1]=0; f[i]=(f[i-1]+m)%i; (i>1)

  2. f[1]=1; f[i]=(f[i-1]+m)%i  (i>1);   if(f[i]==0) f[i]=i;

  3. P(1, m, k)=1 (i = 1);   P(i, m, k)=[P(i - 1, m, k ) + m - 1] % i + 1 (i > 1, 此处先减1是为了让模i的值不为0)

那么这三个公式有什么不同?

首先可以肯定的是这三个公式都正确。公式1,得到的是以0~n-1标注的最终序号;公式2,3得到的就是正常的1~n的序号;并且公式2和公式3其实是一个意思。

下面把公式1推导讲解一下。

公式1的推导:——————————

给出一个序列,从0~n-1编号。其中,k代表出列的序号的下一个,即k-1出列。

a 0, 1, …, k-1, k, k+1, …, n-1

那么,出列的序号是(m-1)%n,k=m%n。出列k-1后,序列变为

b 0, 1, …, k-2, k, k+1, …, n-1

然后,我们继续从n-1后延长这个序列,可以得到

c` 0, 1, …, k-2, k, k+1, …, n-1, n, n+1, …, n+k-2

我们取从k开始直到n+k-2这段序列。其实这段序列可以看作将序列b的0~k-2段移到了b序列的后面。这样,得到一个新的序列

c k, k+1, …, n-1, n, n+1, …, n+k-2

好了,整个序列c都减除一个k,得到

0, 1, …, n-2

c序列中的n-1, n, n+1都减除个k是什么?这个不需要关心,反正c序列是连续的,我们知道了头和尾,就能知道d序列是什么样的。

这样你看,从序列a到序列d,就是一个n序列到n-1序列的变化,约瑟夫环可以通过递推来获得最终结果。ok,继续向下。

剩下的就是根据n-1序列递推到n序列。假设在n-1序列中,也就是序列d中,我们知道了最终剩下的一个序号是x,那么如果知道了x转换到序列a中的编号x`,不就是知道了最终的结果了么?

下面我们就开始推导出序列a中x的序号是什么。

d->c,这个变换很容易,就是x+k;

c->b。从b->c,其实就是0~k-2这段序列转换为n~n+k-2这段序列,那么再翻转回去,简单的就是%n,即(x+k)%n。%n以后,k~n-1这段序列值不会发生变化,而n~n+k-2这段序列则变成了0~k-2;这两段序列合起来,就是序列b。

于是乎,我们就知道了,x`=(x+k)%n。并且,k=m%n,所以x`=(x+m%n)%n=(x+m)%n。公式1就出来了:f[i]=(f[i-1]+m)%i。当然,i=1就是特殊情况了,f[1]=0。这里还有一个小问题。也许你会迷惑为什么x`=(x+m%n)%n=(x+m)%n中的%n变成公式中f[i]=(f[i-1]+m)%i中的%i?其实这个稍微想想就能明了。我们%n就是为了从序列c转换到序列b——这是在n-1序列转换成n序列时%n;那么从n-2转换到n-1呢?不是要%(n-1)了吗?所以这个值是变量,不是常量。

好了,这个最后需要注意的就是从一开始,我们将n序列从0~n-1编号,所以依据公式1得出的序号是基于0开始的。

cdoj525-猴子选大王 (约瑟夫环)的更多相关文章

  1. 约瑟夫环问题(猴子选大王)PHP版

    约瑟夫斯问题问题有时候也被描述成猴子选大王问题,题目如下.(最后会贴上约瑟夫问题的来历) 一群猴子排成一圈,按1,2,…,n依次编号. 然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再 ...

  2. 猴子选大王 (约瑟夫环)(c#)

    猴子选大王问题: 一堆猴子都有编号,编号是1,2,3 ...m ,这群猴子(m个)按照1到m的顺序围坐一圈, 从第1开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子, ...

  3. POJ3750: 小孩报数问题+一道经典约瑟夫问题(猴子选大王)

    又一次因为一个小错误,POJ上Wrong Answer了无数次..... 在差不多要放弃的时候,发现了这个猥琐的不能再猥琐的bug,改完了提交就AC了,简直无语.... 本题wo采用模拟方法: 1 # ...

  4. SYCOJ27猴子选大王

    题目-猴子选大王 (shiyancang.cn) 一.出队顺序Description有M个人,其编号分别为1-M.这M个人按顺序排成一个圈.现在给定一个数N,从第一个人开始依次报数,数到N的人出列,然 ...

  5. sicily 猴子选大王

    题目描述 猴子选大王,有N只猴子,从1-N进行编号.它们按照编号的顺时针方向,排成一个圆圈,然后从第一只猴子开始报数.第一只猴子报1,以后每只猴子报的数字都是它前面猴子所报数字加1.如果一只猴子报的数 ...

  6. PHP编程----猴子选大王

    <?php/** * 猴子选大王 * 17个猴子围成一圈,从某个开始报数1-2-3-1-2-3---报"3"的猴子就被淘汰, * 游戏一直进行到圈内只剩一只猴子它就是猴大王了 ...

  7. PHP洗牌、猴子选大王两个小算法

    <一>洗牌算法 /** *洗牌算法washCard *@param $cardNum *@return array */ function washCard($cardNum) { $ca ...

  8. 猴子选大王的c#实现

    原文地址:猴子选大王的c#实现作者:余文 今天被问到了猴子选大王的意思,题目大意就是说有n只猴子围坐成一个圈,按顺时针方向从1到n编号.然后从1号猴子开始沿顺时针方向从1开始报数,报到m的猴子出局,再 ...

  9. 猴子选大王【PHP】

    目录 猴子选大王 指针解决 数组压栈 猴子选大王 一群猴子排成一圈,按1,2,...,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去...,如此不 ...

  10. C语言程序设计-猴子选大王[链表应用]

    2032 猴子选大王 Description 有N只猴子,从1~N进行编号.它们按照编号的顺时针方向排成一个圆圈,然后从第一只猴子开始报数.第一只猴子报的第一个数字为1,以后每只猴子报的数字都是它们前 ...

随机推荐

  1. java 线程池--ExecutorService

    一 Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. new ...

  2. Prometheus 简介

    Prometheus 是一个开源的服务监控系统和时间序列数据库. 特性: 高维度数据模型 自定义查询语言 可视化数据展示 高效的存储策略 易于运维 提供各种客户端开发库 警告和报警 数据导出   gi ...

  3. Oracle 11gR2 RAC集群服务启动与关闭总结

    引言:这写篇文章的出处是因为我的一名学生最近在公司搭建RAC集群,但对其启动与关闭的顺序和原理不是特别清晰,我在教学工作中也发现了很多学员对RAC知识了解甚少,因此我在这里就把RAC里面涉及到的最常用 ...

  4. ORACLE联机日志文件丢失或损坏的处理方法(转)

    经验总结: 联机日志分为当前联机日志和非当前联机日志,非当前联机日志的损坏是比较简单的,一般通过clear命令就可以解决问题. 损坏非当前联机日志:1.启动数据库,遇到ORA-00312 or ORA ...

  5. jstl_core标签库

    先导入这个 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 1 & ...

  6. autoreconf报错LC_ALL和LANGUAGE未设置

    报错提示: merlin@ubuntu:/opt/smbshared/projects/x86test/openvpn/openvpn-release-2.4$ autoreconf -i -v -f ...

  7. 解决ueditor中没法动态配置imageurlprefix的方法

    [建议使用右边文章中的方法,本篇文章没有真正的解决问题](新)解决php版本ueditor中动态配置图片URL前缀(imageurlprefix)的方法 修改背景,由于后台图片是上传到挂载的静态资源磁 ...

  8. Excel if函数无法正确对比大小

    我想完成以下操作 1.提取A列数字的第7-11位的数字 2.若此数字大于1993 3.则返回20,不然返回0 于是我在B和C列上写了两个函数,分别是 MID(A1,7,4)          IF(B ...

  9. 汇编_压缩BCD码和非压缩BCD码

    BCD码是表示十进制数的,非压缩BCD码是用8位表示的,其实只用低4位,高4位全为0. 例如,十进制数36,用非压缩BCD码表示为:0000 0011 0000 0110 ,这是两个字节. 压缩BCD ...

  10. Tool:Visual Studio Code

    ylbtech-Tool:Visual Studio Code Microsoft在2015年4月30日Build 开发者大会上正式宣布了 Visual Studio Code 项目:一个运行于 Ma ...