题目描述
nn 个人的编号是 1 ~ nn,如果他们依编号按顺时针排成一个圆圈,从编号是 1 的人开始顺时针报数。
(报数是从 1 报起)当报到 kk 的时候,这个人就退出游戏圈。下一个人重新从 1 开始报数。
求最后剩下的人的编号。这就是著名的约瑟夫环问题。
本题目就是已知 n,kn,k 的情况下,求最后剩下的人的编号。
输入描述
输入是一行,2 个空格分开的整数 n, k\ (0 < n,k < 10^7)n,k (0<n,k<107)。
输出描述
要求输出一个整数,表示最后剩下的人的编号。
输入输出样例
示例
输入
10 3
输出
4
运行限制
最大运行时间:1s
最大运行内存: 256M
//这题显然直接思考n的情况复杂,但是一开始的1个人时那
//退出游戏的人就为0个这个非常容易,因此递归非常适合解题
//在递归中已经有n-1这样缩小人数的操作了,
//根本不需要自己删除人数
#include <stdio.h>
#include <stdlib.h>
int bs(int n,int k)
{
if(n==1)
{
return 0;
//return 0是结束当前的这次函数
//接下来就要回到上一次函数
//也不是结束主函数!
}
else
{
return (bs(n-1,k)+k)%n;
//(bs(n-1,k)前一个人退出游戏的结果
//+k为向前数的位数
//%n是报到最后一个人时重新指到第一个人(轮回)
//现在的结果等于前一次报数再走三位
//显然这是退出游戏的人的位置,返回的结果自然是
// 当前退出游戏的人的位置
//你之前还一直想为什么是n-1,为什么要加上这个函数的值
//你根本不用思考为什么是加上这个值,这是模型,
//必须要想到这是上一步的衔接,
//而不是思考为什么是加上上一次的这个数!
//这是递归的基本思想,等于上一次再执行这一次的操作
//整个流程就是上一步操作到下一步,但是上一步没有结果
//就必须要继续往上一步,一直找到结果为止,然后返回答案
//如n-1为n的上一步,没有答案,就一直找到一才有了答案
//然后再从1到2,2到3,逐一赋值,最终才得来的n-1,这就是
//递归,也因此,你必须要设置一个最初的状态,也就是下限
//不然就会死循环无结果
}
}
int main(int argc, char *argv[])
{
int n,k;
scanf("%d%d",&n,&k);
printf("%d",bs(n,k)+1);
//自然退出游戏的人的下一位就是剩下的人的下标
return 0;
}
// 总结:以后遇到每一次都是固定步骤的操作,且前后有连续性的,优先用递归函数解决!