一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
在网上学习别人的解题经验的时候看到这样一个C语言版本的解法,代码如下:
#include<stdio.h>
int main(){
int n,sum=0;
scanf("%d",&n);
for(int i=2;i<=n;i++)
sum=(sum+3)%i;
printf("%d",sum+1);
return 0;
}
这么短的代码竟然解决了问题!!!所以,芝士就是力量~决定学习一下数学问题背后的规律
约瑟夫环问题,这是一个很经典算法,处理的关键是:伪链表
问题描述:N个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,报到m的人出圈;如此往复,直到所有人出圈。(模拟此过程,输出出圈的人的序号)
void joseph(int count, int doom) {
int alive = count; //幸存人数
int number = 0; //计数,当number==doom时,淘汰这个人
int index = 0; //下标,为总人数-1
int *circle = NULL; //根据需求设为循环数组,存储每个人
//用calloc()函数申请得到的空间,自动初始化每个元素为0
//所以,0表示在这个人在约瑟夫环内,1表示这个人出圈,即“淘汰”
circle = (int *) calloc(sizeof(int), count);
//只要幸存人数大于0,则一直进行循环
while(alive > 0) {
number += 1- circle[index]; //每轮到一个人报数,不管是"0"还是"1"都进行计数
if(number == doom) { //当number==doom时,就要淘汰当前这个人
/*
淘汰一个人需要做四步操作:
1、输出这个人的位置
2、把这个人的状态从在圈内"0"改为不在圈内"1"
3、幸存人数alive--
4、 计数器number归零
*/
alive == 1 ? printf("%d", index+1) : printf("%d,", index+1);
circle[index] = 1;
alive--;
number = 0;
}
//与总人数count取余,则可以使index在0~count-1之间 一直循环,达到循环数组的目的
index = (index +1) % count;
}
printf("\n");
free(circle); //结束后一定要释放circle所申请的空间
}
原文:https://blog.csdn.net/weixin_38214171/article/details/80352921