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. 寒假训练3解题报告 CodeForces #148

    CodeForces 148B 一道简单模拟,判断龙能够抓到公主几次,如果公主和龙同时到达公主的城堡,不算龙抓住她,因为路程除以速度可能会产生浮点数,所以这里考虑一下精度问题 #include < ...

  2. 数位dp 3943 二分法

    转载:http://blog.csdn.net/wdcjdtc/article/details/39177905 #include"cstdlib" #include"c ...

  3. 解决Android Studio2.0不能使用HttpClient

    在build.gradle中的android {}中加上useLibrary 'org.apache.http.legacy'

  4. hdu4696 Answers(循环节+找规律)

    题意: 分析: 容易想到先把T数组按位置和对应权值建一个有向图(类似置换群那种指法) 然后图建完了,如果C[]里面都是2,那显然只能凑出那些偶数,奇数是不能凑出来的 如果C[]有1有2呢? 事实上是可 ...

  5. Ubuntu 16.04无法在WPS中输入中文的问题解决

    1. sudo gedit /usr/bin/wps 增加 export XMODIFIERS="@im=fcitx" export QT_IM_MODULE="fcit ...

  6. [大雾雾雾雾] 告别该死的 EFCore Fluent API

    [EF Core Oracle  列名大小写问题] [EF Core Oracle column name case problem] [EF Core PostgreSql 列名大小写问题] [EF ...

  7. 手动加入SSH支持、使用c3p0

    之前做的笔记,如今整理一下.大家有耐心的跟着做就能成功: SSH(struts2.spring.hibernate) *  struts2      *  充当mvc的角色 *  hibernate ...

  8. x86CPU 实模式 保护模式 傻傻分不清楚? 基于Xv6-OS 分析CR0 寄存器

    基于Xv6-OS 分析CR0 寄存器 之前一直认为晕乎乎的...啥?什么时候切换real model,怎么切换,为什么要切换? ------------------------------------ ...

  9. Linux---有关dig命令的有用脚本

    这里直接给出脚本以及运行的效果图,主要推断了一下cdn然后能够直接过滤url.默认就是dig +域名 +short. 脚本qdig(随便能够取一个名字)例如以下: #!/usr/bin/env bas ...

  10. formData 对象

    (1)创建的formData打印为空? var edition=$("#edinum").val();//版本号 var uploader=$("#upman" ...