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. [BZOJ3751][NOIP2014]解方程(数学相关+乱搞)

    题目描述 已知多项式方程: a0+a1x+a2x^2+..+anx^n=0 求这个方程在[1, m ] 内的整数解(n 和m 均为正整数) 输入输出格式 输入格式: 输入文件名为equation .i ...

  2. [NOIP2007] 普及组

    奖学金 模拟 开个struct排序即可 c++吼啊 /*by SilverN*/ #include<algorithm> #include<iostream> #include ...

  3. 【Java集合】Java中集合(List,Set,Map)

    简介: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),而JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! JAVA集 ...

  4. POJ 3468_A Simple Problem with Integers(树状数组)

    完全不知道该怎么用,看书稍微懂了点. 题意: 给定序列及操作,求区间和. 分析: 树状数组可以高效的求出连续一段元素之和或更新单个元素的值.但是无法高效的给某一个区间的所有元素同时加个值. 不能直接用 ...

  5. Just a Hook-HDU1698(线段树求区间)

    http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem Description In the game of DotA, Pudge’s meat ...

  6. 2017-10-02-afternoon

    T1 最大值(max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目: 这里有一个长度 ...

  7. Java 添加、更新和移除PDF超链接

    简介 PDF超链接用一个简单的链接包含了大量的信息,满足了人们在不占用太多空间的情况下渲染外部信息的需求.下面将介绍通过Java 在PDF中添加.更新和移除超链接. (一)工具使用: Free Spi ...

  8. mac idea快捷键(部分常用)

    shift+F6重命名 shift+enter 换到下一行 shift+F8等同eclipse的f8跳到下一个断点,也等同eclipse的F7跳出函数 F8等同eclipse的f6跳到下一步F7等同e ...

  9. Servlet的文件上传

    以下内容引用自http://wiki.jikexueyuan.com/project/servlet/file-uploading.html: Servlet可以与HTML form标签一起使用允许用 ...

  10. oracle11g expdp/impdp数据库

    oracle11g导入/导出数据库 导出 .创建目录 sqlplus / as sysdba create directory dbDir as 'd:\oralce_sdic_backup\'; g ...