ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

试题 历届真题 约瑟夫环【第九届】【决赛】【A组】

2022-02-02 20:33:10  阅读:189  来源: 互联网

标签:11 第九届 下标 试题 真题 位置 胜出 编号 报数


资源限制

时间限制:1.0s 内存限制:256.0MB

  n 个人的编号是 1~n,如果他们依编号按顺时针排成一个圆圈,从编号是1的人开始顺时针报         数。
  (报数是从1报起)当报到 k 的时候,这个人就退出游戏圈。下一个人重新从1开始报数。
  求最后剩下的人的编号。这就是著名的约瑟夫环问题。

  本题目就是已知 n,k 的情况下,求最后剩下的人的编号。

  题目的输入是一行,2个空格分开的整数n, k
  要求输出一个整数,表示最后剩下的人的编号。

  约定:0 < n,k < 1百万

  例如输入:
  10 3

  程序应该输出:
  4

题目分析:

由于输入的数字数据太大,达到百万,正常的链表计算约瑟夫圆环肯定超时,那么我们可以用递推的方式进行求解。

递推公式

                            f(N,M)=(f(N-1,M)+M)%N

f(N,M)表示,N个人报数,每报到M时杀掉那个人,最终胜利者的编号。
f(N−1,M)表示,N-1个人报数,每报到M时杀掉那个人,最终胜利者的编号。

下面我们不用字母表示每一个人,而用数字。
                        1、2、3、4、5、6、7、8、9、10、11

表示10个人。他们先排成一排,设定报数3的人出局。

刚开始的时候,从编号1开始报数,第一轮出局的是是编号3。

第一轮过后,编号为4的人报1,第二轮出局的是编号6。

第二轮过后,编号为7的人报1,第三轮出局的是编号9。

第三轮过后,由于总共是11人,编号10报数1,编号11报数2,编号1报数3,编号1出局。

依次类推,游戏胜出者就是编号7。

下图表示这一过程(先忽视绿色的一行)

 现在我们来推导一下这个递推公式

将上面表格的每一行看成数组,这个公式描述的是:游戏胜出者在这一轮的数组下标位置

f(1,3)=0:只有一个人,这个人就是游戏胜出者,此时他的下标位置是0

f(2,3)=(f(1,3)+3)%2=3%2=1:在有2个人的时候,胜出者的下标位置是1

f(3,3)=(f(2,3)+3)%3=4%3=1:在有3个人的时候,胜出者的下标位置为1

f(4,3)=(f(3,3)+3)%4=4%4=0:在有4个人的时候,胜利者的下标位置为0

·······

最后 f(11,3)=6 (注意此时得到的是数组下标位置,最后应该+1才是编号) 

下面将讲解怎么推导这个公式。

1、假设我们知道了11人的时候,胜出者的下标位置是6,那么经过第一轮游戏之后,剩下10个人,应该是3,是向前移动了3位,为什么呢,因为前一轮已经走过了三个人,在走过了上一轮之后,原本报4的人,反而成了报1的人,所以得到胜出位置的这个3就是之前的6往前移动了3位。(此时也需要考虑数组越界问题,由于我们是用递推公式,在下一个假设中利用公式的取模即可)

2、同理倒着思考,假设知道了10个人的时候,胜出者的下标位置是3,有11个人的时候,同理推出他的下标位置应该向后移动3位,也就是加上3。但是因为数字的长度有限制,肯定不能让数组越界,所以要取模,得到数组位置,所以是f(11,3)=(f(10,3)+3)%11。

3.根据上面两点,此时整体看这个公式,此时有N个人,报数为M的出局,那么此时的数组应该是怎么移动的呢?

开局时,胜出者的位置是:f(N,M)=(f(N-1,M)+M)%N

当出局一人的时候,他的下一个人成为头部,报数1,此时相当于原数组向前移动了M个位置,此时有N-1个人,此时胜出者的位置是f(N-1,M)=(f(N-2,M)+M)%(N-1),依次类推,因为f(1,M)=1是一定的,这是递推的初始条件,那么我们就可以根据公式得出最后胜出者的位置。

理解这个递推式的核心在于关注胜出者的下标位置是怎么变的。每出局一个人,其实就是把这个数组向前移动了M位。然后逆过来,就可以得到这个递推式。

因为求出的结果是数组中的下标,最终的编号还要加1


import java.util.*;
public class Main {
	public static void cir(int n,int m) {
		int p=0;
   //当n=1的时候 p还是0 不进入循环 直接输出即可
		for(int i=2;i<=n;i++) {
    //为何从2开始呢,因为开始只有1个人的时候不用计算,返回的位置肯定是0
    //所以循环要从2开始
			p=(p+m)%i;
		
		}
		System.out.println(p+1);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader =new Scanner(System.in);
		int n=reader.nextInt();
		int m=reader.nextInt();
		cir(n,m);
	}

}

标签:11,第九届,下标,试题,真题,位置,胜出,编号,报数
来源: https://blog.csdn.net/qq_54832724/article/details/122771526

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有