方法是来自B站@麦克老师讲算法(链接:BV1so4y1o7KJ),然后我再进行了一些优化。
#include<stdio.h>
int main()//总共n个人,围成圈报数,报数为m,的人出局,剩下的人继续,找到剩下的最后一个人
{
int m,n;
int cnt=0,k=0,i=0;
scanf("%d %d",&n,&m);//总共n个人,数到报数报到m的人出局
int a[n]={0};
while(cnt<n-1)//cnt是出局的人数,应该要小于总人数-1,表示剩下最后的n-m,表示最后剩下m个人
{ //此处n-1则表示最后剩下一个人
i++;//i表示第几个人,从第一个人开始往后
if(i>n)i=1;//报数到最后一个人,又回到前面,相当于围成一个圈
if(a[i-1]==0)//a[0]对应的是1,可以表示人的位置(用数组元素表示人的位置)
{
k++;//表示报的数1 2 3,1 2 3,1 2 3 ...
if(k==m){//如果报数为m,则出局
a[i-1]=1;//将其位置置为1,表示这个人已经出局
cnt++;//出局一个人cnt加1
k=0;//
}
}
}for(i=0;i<n;i++){
if(a[i]!=1){//便历数组,看哪个位置还有人
printf("%d",i+1);//输出这个人,是第几个人(第0个位置上站的是第一个人)
}
}
return 0;
}
//举个栗子!!!
//1 2 3 4 5 6 7 8 9 10 最初有10个人(自此为第一行,往下,单数行表示剩下的人数,偶数行表示剩下的人所报的数的数据)
//1 2 3 1 2 3 1 2 3 1 这十个人报数,报到三的出局
//1 2 4 5 7 8 10 出局三个人,剩下7个
//2 3 1 2 3 1 2 继续报数,从最前面的人接着报(想像成一个圈),所以此处最前头是2,是因为接着上面第10报的1
//1 4 5 8 10
//3 1 2 3 1
//4 5 10
//2 3 1
//4 10
//2 3
//4//最后剩下的是原来站位的第四人