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. TYVJ1716 上帝造题的七分钟

    时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 裸体就意味着身体. 描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵.第二分钟,L说, ...

  2. 主席树初探--BZOJ3524: [Poi2014]Couriers

    n<=500000个数,m<=500000个询问,每次问区间里出现次数>(R-L+1)的数字是谁,没有输出0. 写了带修改发现不会不带修改了.... 不带修改的话,n个点,每个点表示 ...

  3. java 判断一个字符串是否为纯数字

    if (getUid().matches("[0-9]+")) { Log.v("纯数字");} else { Log.v("非纯数字"); ...

  4. Kafka 生产消费 Avro 序列化数据

    https://unmi.cc/kafka-produce-consume-avro-data/ https://unmi.cc/apache-avro-serializing-deserializi ...

  5. HDU 5640 King's Cake【模拟】

    题意: 给定长方形,每次从中切去一个最大的正方形,问最终可以得到多少正方形. 分析: 过程类似求gcd,每次减去最小的边即可. 代码: #include <cstdio> #include ...

  6. cogs——8. 备用交换机

    8. 备用交换机 ★★   输入文件:gd.in   输出文件:gd.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] n个城市之间有通讯网络,每个城市都有通讯交换机,直 ...

  7. Python安装与基本数据类型

    人生苦短,我选Python. Python比其他的语言来说真的简洁多了,很多时候想做的东西都有对应的模块可以导入,平时玩点小东西真心不错. 首先讲一下安装,其实没什么好讲的,点点点点点,完事. 这里的 ...

  8. LOAP& its implimenlation

    LDAP 概念 LDAP的英文全称是Lightweight Directory Access Protocol,简称为LDAP,LDAP是轻量目录访问协议,LDAP是轻量目录访问协议.简单的说来,LD ...

  9. 洛谷 P1404 平均数

    P1404 平均数 题目描述 给一个长度为n的数列,我们需要找出该数列的一个子串,使得子串平均数最大化,并且子串长度>=m. 输入输出格式 输入格式: N+1行, 第一行两个整数n和m 接下来n ...

  10. ios计算字符串宽高,指定字符串变色,获取URL参数集合

    #import <Foundation/Foundation.h> @interface NSString (Extension) - (CGFloat)heightWithLimitWi ...