传说约瑟夫当年活下来就是靠快速计算这个问题。
n 个人围成一圈,编号依次为1,2,3...n。 从第一个人开始报数,数到 m 的人出列,再由下一个人重新从 11 开始报数,数到 m 的人再出圈。 以此类推,直到所有的人都出列。 请输出依次出圈人的编号。
输入格式
两个整数 n,m 1 =n,m <= 100。
输出格式
n 个用空格分隔的整数,表示出圈人的编号。
示例输入
6 4样品输出
4 2 1 3 6 5
解题思路
1.定义数组a[1,2,.....n]编号对应数组数字
2.定义i,j
i表示报的数(用于淘汰人)(淘汰的人数组中的数变为0)
j表示报数字的次数(用于对应位置)
3.增加i开始报数
当i对应的数组中的数为0时i--(跳过次人)
用(j-1)%n+1表示当前人的位置当
(j-1)%n+1(当J为n的倍数时不会=0而是=n)
4.i最大值为n*m
当i=n*m时停止输出(j-1)%n
#include<stdio.h>
int main(){
int n,m;
scanf("%d %d",&n,&m);
int i=1;
int a[100];
while(i<=n){
a[i]=i;
i++;
}//所有数组的数存自己编号
int j=1;
i=1;
while(1){
if(a[(j-1)%n+1]==0){
i--;
}
if(i%m==0 && a[(j-1)%n+1]!=0){//当i为m的倍数且此时此位置的数不是已经淘汰的数
if(j%n==0){//如果时最后一个数则a[n]=0
a[n]=0;
printf("%d ",n);
}else {//如果不是最后一个数则此数变为0(淘汰)
a[(j-1)%n+1]=0;
printf("%d ",(j-1)%n+1);
}
}
i++;
j++;
if(i==n*m){//i为最大值输出最后一个
printf("%d",(j-1)%n);
break;
}
}
i=0;
return 0;
}