#include <stdio.h>
void main()
{
int n,m;
int k = 0;
int number = 0;
scanf("%d%d",&n,&m);
if (n<=0 || n>=20 || m<=0 || m>=20)
printf("ERROR");
else
{
int a[20];
int p[20];
int i,j;
for(i=0;i<n;i++)
{
a[i]=i+1;
}
for(j=0;;)
{
if (a[j]!=0)
{
number++;
if (number%m == 0)
{
p[k] = a[j];
k++;
a[j] = 0;
}
if (k == n)
break;
}
j++;
j = j%n;
}
int x;
for (x = 0 ; x<n ;x++)
printf("\t%d",p[x]);
}
}
#include <stdio.h>
void main()
{
int n,m;//n是人数 m是报到要出列的数
int k = 0;//k代表已经出列的人数
int number = 0;//number是正在报的数
scanf("%d%d",&n,&m);
if (n<=0 || n>=20 || m<=0 || m>=20)
printf("ERROR");//烦人的判断过程
else//正式开始
{
int a[20];//a[]数组用来存放人的序号
int p[20];//p[]数组用来依次存放出列的人的序号
//因为m、n都小于20 所以定义两个长度为20的数组即可
int i,j;
for(i=0;i<n;i++)
{
a[i]=i+1;
}
//因为a[i]数组的序号是从0开始的 所以每项都+1后就会变成我们熟悉的项数
//比如a[0]=1 a[1]=2 这时的a[]数组里存的就是人的序号 第一项就是1 第二项是2
for(j=0;;)//for循环进入 但不写终止条件和递增条件 后面利用break和j++进行
{
if (a[j]!=0)//一开始所有数都不是0 所以条件语句满足
{
number++;//若满足条件语句 说明成功报数 number加1
if (number%m == 0)//如果number除以目标数=0 那么number就是目标数或者其倍数 此时这个人需要出列
{
p[k] = a[j];//把每次出列a[j]里存储的序号放到p[]数组里面
k++;//k++保证了第一次出列放在p[0],第二次放在p[1],也就是按顺序排列
a[j] = 0;//这个人出列以后 序号变成0
//这样下一次判断a[j]是否为0是就会出现条件不成立的情况
//条件不成立 number就不会增加 相当于跳过了这个人直接到下一个
//由此来模拟已经出列的人不会参加以后的报数
}
if (k == n) //如果 k=n了说明所有人都已经出列 那么利用break结束循环
break;
}
j++;//一个人报完数 j++轮到第二个人报数
j = j%n;//这一步达到模拟循环报数的目的 不能省 否则死循环
//例如总共5个人
//当j<5时 余数就是本身 比如4除以5 商0余4 那么j的值不会变
//也就是算完了j=4(因为a[4]是第5项也就是最后一个人)之后
//j++即j=5时 余数为0
//那么j又回到了0 而a[0]就是第一项 相当于实现了循环报数
//这个地方有点绕 因为数列的下标和项数之间有一个1的差值
//所以你要明白a[0]是第一项而a[1]不是第一项
}
int x;
for (x = 0 ; x<n ;x++)
printf("\t%d",p[x]);//利用循环 遍历整个数组依次输出即可
}
}