N个人坐成一个圆环(编号为1 - N),从第1个人开始报数,数到K的人出列,后面的人重新从1开始报数。问最后剩下的人的编号。
例如:N = 3,K = 2。2号先出列,然后是1号,最后剩下的是3号。
Input
2个数N和K,表示N个人,数到K出列。(2 <= N, K <= 10^6)
Output
最后剩下的人的编号
Input示例
3 2
Output示例
3
解:

 #include <stdio.h>
int main()
{
int n, k;
while (scanf_s("%d%d", &n, &k) != EOF)
{
int move = ;
for (int i = ; i <= n; i++) move = (move + k) % i;
printf("%d\n", move + );
}
}

首先,我是从正向思考,即找出每次去掉的元素,并标记,循环n-1次,最后找到未标记的元素即可。这个思路简单,但实现却麻烦。
然后,是用链表的删改来完成游戏成员的淘汰,删除n-1个节点,最后剩余的就是winner。但这仍不够简单。
最后,注意到约瑟夫环的环状结构的特性,使我们可以利用当k为相同值时,n-1个人玩游戏和n个人玩游戏存在的数学关系解决问题。
这种数学关系简单叙述如下:
n个人玩游戏,k为常数,定义f(n)为n人游戏时的胜利者编号。第一轮淘汰者为(k-1)%n+1(为什么不是k%n?注意取模运算的范围为[0,n-1],考虑k=n的情况),之后我们可以将(k-1)%n+2作为新的排头head,(k-1)%n为尾tail,以另一种方式展开这个环。
由于head=1,tail=n-1时,winner=f(n-1),
则head=(k-1)%n+2,tail=(k-1)%n时,winner=winner+(k-1)%n+1。(考虑到加法中可能存在的“溢出”问题,将公式标准化如下)

winner=f(n-1)+(k-1)%n+1-1)%n+1=(f(n-1)+(k-1)%n)%n+1=(f(n-1)+k-1)%n+1。

所以我们得到递推公式如下:
定义f(n)为n人游戏时的胜利者编号,k由题目定义,
则 f(1)=1;
  f(n)=(f(n-1)+k-1)%n+1;
由于取模运算的范围包括零,所以我们在运算前要-1,运算后要+1。那我们可不可以将这个步骤省略呢?
我们需要改变f(n)的定义,即将f(n)定义为f(n)-1(其实这时候的f(n)可以理解为偏移量,它的值代表的是n人游戏时获胜者的相对于零位置的位置),
所以递推公式化简为:f(1)=0;
          f(n)=(f(n-1)+k)%n;(最终答案不要忘记+1!)

(数论)51NOD 1073 约瑟夫环的更多相关文章

  1. 51nod 1073 约瑟夫环

    题目链接 先说一下什么是约瑟夫环,转自:传送门 关于约瑟夫环问题,无论是用链表实现还是用数组实现都有一个共同点:要模拟整个游戏过程,不仅程序写起来比较烦,而且时间复杂度高达O(nm),当n,m非常大( ...

  2. 51nod 1073约瑟夫环

    思路传送门 :http://blog.csdn.net/kk303/article/details/9629329 n里面挑选m个 可以递推从n-1里面挑m个 然后n-1里面的x 可以转换成 n里面的 ...

  3. 51 Nod 1073 约瑟夫环

    1073 约瑟夫环  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 N个人坐成一个圆环(编号为1 - N),从第1个人开始报数,数到K的人出列,后面的人 ...

  4. Java实现约瑟夫环

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

  5. poj 3517 约瑟夫环

    最简单的约瑟夫环,虽然感觉永远不会考约瑟夫环,但数学正好刷到这部分,跳过去的话很难过 直接粘别人分析了 约瑟夫问题: 用数学方法解的时候需要注意应当从0开始编号,因为取余会等到0解. 实质是一个递推, ...

  6. C++ 约瑟夫环

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

  7. 用pl/sql游标实现约瑟夫环

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

  8. 通过例子进阶学习C++(七)CMake项目通过模板库实现约瑟夫环

    本文是通过例子学习C++的第七篇,通过这个例子可以快速入门c++相关的语法. 1.问题描述 回顾一下约瑟夫环问题:n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 m 个人,让他出局:然 ...

  9. php解决约瑟夫环

    今天偶遇一道算法题 "约瑟夫环"是一个数学的应用问题:一群猴子排成一圈,按1,2,-,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数, 再数到第m只,在把 ...

随机推荐

  1. 计算1+2+...+100之和<for循环的学习>

    #include <stdio.h> /* 计算1+2+....+100 soulsjie 20170525 */ void main(){ int i; int s=0; for(i=0 ...

  2. 添物不花钱学JavaEE(基础篇) --HTML

    HTML是什么? HTML – Hyper Text Markup Language HTML官方网址 http://www.w3.org/TR/2014/REC-html5-20141028/ 其实 ...

  3. j简单的分类实现-K近邻

          dataSetSize=dataSet.shape[0]                          voteIlabel=labels[sortedDistIndicies[i]] ...

  4. Linux下汇编语言学习笔记4 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  5. SQLSERVER数据库管理员的专用连接DAC

    出处: http://www.cnblogs.com/lyhabc/archive/2012/09/23/2698702.html DAC:Dedicated Admin Connection 当SQ ...

  6. Ubuntu系统备份工具大全(官方整理推荐)

    其实官方在系统备份这块已经有Wiki整理和收集各类实用的工具.以下是翻译自官方Wiki的部分文档: 备份工具  wiki文档实用程序 工具 界面 格式类型 Raw/File 支持 远程 增量 差异 自 ...

  7. maven提示“编码 GBK 的不可映射字符”问题的解决

    pom.xml中加上如下代码 <properties> <!-- spring版本号 --> <spring.version>4.2.3.RELEASE</s ...

  8. Sql查询一个列对应多个列

    Sql查询一个列对应多个列 今天遇到一个问题,表table1有两个字段col1.col2两个字段.先记录下来,以后有个参考. 现在需要查询出的数据满足如下要求: 1.col1重复.col2重复的数据只 ...

  9. 【python】一些好的学习网址

    http://www.cnblogs.com/BeginMan/p/3179302.html http://www.cnblogs.com/huxi/category/251137.html http ...

  10. SAP ABAP 的经常使用debug方式

    SAP ABAP 的经常使用debug方式: 1. 直接在程序中设断点 在se38里面打上breakpoint,程序执行到该处即进入debug模式 2.background Job的debug 进入S ...