题目:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。
方法一:
#include <stdio.h>
#define N 10
int main()
{
int a[N]; // 用数组保存参与报数的人员编号
int i, j, m, out, count;
// 初始化编号,从1开始连续编号
for (i = 0; i < N; i++) {
a[i] = i + 1;
}
i = 0; // i表示当前参与报数的人员在数组中的下标
m = 3; // 每次报数的个数
out = 0; // 记录已经退出报数的人数
count = 0; // 记录当前已经报数的次数
// 当还有人参与报数时循环
while (out < N) {
// 如果这个人还没退出
if (a[i] != 0) {
count++; // 增加报数次数
// 如果报数次数达到了m
if (count == m) {
printf("%d ", a[i]); // 输出该人员编号
a[i] = 0; // 标记该人员已经退出
out++; // 增加退出人数
count = 0; // 将报数次数清零
}
}
i++; // 指向下一个人员
// 如果已经扫描完一圈,则重新开始
if (i == N) {
i = 0;
}
}
return 0;
}
程序中,首先定义了一个长度为10的数组,用于保存参与报数的人员编号。然后初始化编号,从1开始连续编号。接着设定了3个变量:i表示当前参与报数的人员在数组中的下标,m表示每次报数的个数,out表示已经退出报数的人数,count表示当前已经报数的次数。
接下来,使用while循环来模拟报数的过程。首先判断当前参与报数的人员是否已经退出,如果还没退出,则增加报数次数count。如果报数次数达到了m,则输出该人员编号,标记该人员已经退出(将其编号置为0),增加退出人数out,并将报数次数count清零。接着将下标i指向下一个人员,如果已经扫描完一圈,则将下标重新指向第一个人员。最终,当所有人都退出报数时,程序结束。
方法二 (万能):
#include <stdio.h>
int main()
{
int n, m;
printf("请输入参与游戏的人数:");
scanf("%d", &n);
printf("请输入报数的上限:");
scanf("%d", &m);
int a[n];
for(int i = 0; i < n; i++)
{
a[i] = i + 1;
}
int k = 0;
while(n > 0)
{
k += m - 1;
if(k >= n)
{
k %= n;
}
printf("%d ", a[k]);
for(int i = k; i < n - 1; i++)
{
a[i] = a[i + 1];
}
n--;
}
return 0;
}
运行该程序,按照提示输入参与游戏的人数和报数的上限,程序就会自动进行转圈报数,并输出出局人员的编号。
方法三(指针):
以下是C语言指针处理的代码实现:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n, k = 0, m = 3;
printf("请输入参与游戏的人数:");
scanf("%d", &n);
int *a = (int*)malloc(n*sizeof(int)); // 动态分配内存空间
for(int i = 0; i < n; i++)
{
*(a + i) = i + 1; // 初始化,编号从1开始
}
while(n > 1)
{
k = (k + m - 1) % n;
for(int i = k + 1; i < n; i++)
{
*(a + i - 1) = *(a + i);
}
n--;
}
printf("最后留下的是编号为%d的人\n", *a);
free(a); // 释放内存空间
return 0;
}
首先使用动态分配内存空间,然后初始化参与者编号,随后通过指针实现转圈报数,最后输出留下的人员编号,并释放内存空间。