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. vs2013 + python3.52 + boost1.61, 编译C++库失败

    使用vs2013  + python3.52 + boost1.61,  编译C++库,  失败!  提示如下": boost::python::detail::init_module(st ...

  2. php用smtp方式发送邮件

    http://www.daixiaorui.com/read/16.html 2个比较经典的PHP加密解密函数分享 http://www.jb51.net/article/51706.htm php5 ...

  3. python编程规范系列--建议01~07

    本系列来自<编写高质量代码 改善python程序的91个建议>的读书笔记整理. 本书主要内容     1)容易被忽视的重要概念和常识,如代码的布局和编写函数的原则等:     2)编写py ...

  4. Hibernate学习11——Hibernate 高级配置(连接池、log4j)

    第一节:配置数据库连接池 这里配置c3p0连接池,需要的jar包: jar包位于hibernate压缩包的:hibernate-release-4.3.5.Final\lib\optional\c3p ...

  5. struts2学习(8)struts标签1(数据标签、控制标签)

    一.struts2标签简介: struts标签很多,功能强大,这是优点: 但是缺点的话,性能方面可能会,各方面速度啊啥的会降低:有人比较测试,struts性能比jstl低很多:   二.struts2 ...

  6. appium+python自动化28-name定位

    前言 appium1.5以下老的版本是可以通过name定位的,新版本从1.5以后都不支持name定位了 name定位报错 1.最新版appium V1.7用name定位,报错: selenium.co ...

  7. Linux学习笔记 - Shell 输出命令

    1. echo 命令 echo 是基本的shell输出命令,她的语法是: echo string 我们也可以使用她来定制一些输出的格式,具体如下: 输出普通字符串 echo "it is a ...

  8. 根据段落编号自动添加书签的VBA

    Sub 宏1() ' ' 宏1 宏 ' '    Dim myRange As Word.Range Dim num As String, content As String Selection.Ho ...

  9. 六、配置github的pull request触发jenkins自动构建

    之前的配置,都是向master分支push操作触发jenkins进行构建,但是在一般的正常工作中,不会允许程序员直接向主分支推送代码:正常都是fork一个本地的分支,在本地分支调试完后,向主干分支提交 ...

  10. C# 设计模式-单例模式(Singleton)

    所谓单例模式即所谓的一个类只能有一个实例,说白了,也就是类只能在内部实例一次,然后提供这一实例,外部无法对此类实例化. 单例模式的特点: 1.只能有一个实例: 2.只能自己创建自己的唯一实例: 3.必 ...