7-28 猴子选大王(20分)
一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
输入样例:
11
输出样例:
7
题解:
# include <stdio.h>
int main()
{
int n;
scanf("%d", &n); // 输入猴子的数量
int m = 3; // 变量m记录报到哪个数要退出圈子
int s = n; // 变量s记录当前在圈内的猴子数
int a[1005] = {0}; // 数组a记录这n个猴子是否在圈内,初始值全为0,表示n个猴子全部在圈内,出圈后应修改元素为1
int k = 0, p = 0; // 变量k记录当前报数是多少,变量p记录当报到最后一个猴子时,反过来从前面的哪个位置开始报数
while (s)
{
// 当圈内有猴子时进行循环
while (a[p] != 0)
{ /* 找到本次报数从第几个猴子开始报数
* 就是找剩下元素是0的猴子接着报数
* 找到起始报数1~3位置
* 再遍历一遍 */
++p;
}
// p就是起始位置猴子报1
for (int i = p; i < n; ++i)
{ // 遍历数组a
if (!a[i])
{ // 如果第i+1个猴子在圈内,
++k; // 报数加1
if (k == m)
{ // 恰好报到m
if (s == 1) // 剩余最后一只猴
{
printf("%d", i + 1); // 输出猴王的编号
}
a[i] = 1; // 修改对应元素为1
--s; // 圈内的猴子总数要相应减1
k = 0; // 报数归零,从0开始,报1~3
}
}
}
}
return 0;
}