习题8-4 报数 (20分)

报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。

本题要求编写函数,给出每个人的退出顺序编号。

函数接口定义:

void CountOff( int n, int m, int out[] );
 

其中n是初始人数;m是游戏规定的退出位次(保证为小于n的正整数)。函数CountOff将每个人的退出顺序编号存在数组out[]中。因为C语言数组下标是从0开始的,所以第i个位置上的人是第out[i-1]个退出的。

裁判测试程序样例:

#include <stdio.h>
#define MAXN 20

void CountOff( int n, int m, int out[] );

int main()
{
    int out[MAXN], n, m;
    int i;

    scanf("%d %d", &n, &m);
    CountOff( n, m, out );   
    for ( i = 0; i < n; i++ )
        printf("%d ", out[i]);
    printf("
");

    return 0;
}

/* 你的代码将被嵌在这里 */
 

输入样例:

11 3
 

输出样例:

4 10 1 7 5 2 11 9 3 6 8 


  1 /*
  2 个人觉得这道题十分具有迷惑性,
  3 一排从1到n的人是一组“数”,报的数又是一组数,
  4 但是之前报过数的人不能再报数,所以每报完一个人都会产生一组新的“数”。
  5 总的来说有三组数,n个人,报的n个数,每隔m个人退出。
  6 */
  7 
  8 void CountOff( int n, int m, int out[] ){
  9     int s[n];
 10     int cnt=1;
 11     int j=1;
 12     int k=0;
 13     //刚开始所有人都没报数,因此全部赋值为0
 14     for(int i=0;i<n;i++){
 15         out[i]=0;
 16     }
 17     //从数1开始报,直到n个人都报过数,因此是cnt<=n
 18     while(cnt<=n){
 19         //报到m就重启
 20         if(j==m+1){
 21             j=1;
 22         }
 23         for(;j<=m;j++){
 24             //已经报过就跳过,直到没报的人继续报
 25             while(out[k]!=0){
 26                 k++;
 27                 //轮完一轮从头开始
 28                 if(k==n){
 29                     k=0;
 30                 }
 31             }
 32             //报数
 33             if(j==m){
 34                 out[k]=cnt;
 35                 cnt++;
 36             }
 37             //报完下一个
 38             k++;
 39             //轮完一轮从头开始
 40             if(k==n){
 41                 k=0;
 42             }
 43         }
 44     }
 45 }
 46 
 47 /*
 48     起始值j=1,k=0,cnt=0 
 49     => k++,for循环完成一次j++;此时k=1,j=2 
 50     => k++,for循环完成两次j++;此时k=2,j=3 
 51     => 由于j==m,计数cnt++,cnt=1,输出out[2]=1,k++,for循环完成三次j++,此时k=3,j=4
 52     => 跳出循环重新给j赋值,此时k=3,j=1 
 53     => k++,for循环完成一次j++;此时k=4,j=2 
 54     => k++,for循环完成两次j++;此时k=5,j=3 
 55     => 由于j==m,计数cnt++,cnt=2,输出out[5]=2,k++,for循环完成三次j++,此时k=6,j=4
 56     => 跳出循环重新给j赋值,此时k=6,j=1
 57     => k++,for循环完成一次j++;此时k=7,j=2 
 58     => k++,for循环完成两次j++;此时k=8,j=3 
 59     => 由于j==m,计数cnt++,cnt=3,输出out[8]=3,k++,for循环完成三次j++,此时k=9,j=4
 60     => 跳出循环重新给j赋值,此时k=9,j=1
 61     => k++,for循环完成一次j++;此时k=10,j=2 
 62     => k++,k==11,到达数组极限,重新给k赋值,此时k=0
 63     => for循环完成两次j++,此时k=0,j=3
 64     => 由于j==m,计数cnt++,cnt=4,输出out[0]=4,k++,for循环完成三次j++,此时k=1,j=4
 65     => 跳出循环重新给j赋值,此时k=1,j=1
 66     => k++,for循环完成一次j++;此时k=2,j=2 
 67     => out[2]!=0,计数失败一次,k++;此时k=3,j=2
 68     => k++,for循环完成两次j++;此时k=4,j=3
 69     => 由于j==m,计数cnt++,cnt=5,输出out[4]=5,k++,j++;此时k=5,j=4
 70     => 跳出循环重新给j赋值,此时k=5,j=1
 71     => out[5]!=0,计数失败一次,k++;此时k=6,j=1
 72     => k++,for循环完成一次j++;此时k=7,j=2
 73     => k++,for循环完成两次j++;此时k=8,j=3
 74     => out[8]!=0,计数失败一次,k++;此时k=9,j=3
 75     => 由于j==m,计数cnt++,cnt=6,输出out[9]=6,k++,j++;此时k=10,j=4
 76     => 跳出循环重新给j赋值,此时k=10,j=1
 77     => k++,k==11,到达数组极限,重新给k赋值,此时k=0
 78     => for循环完成一次j++,此时k=0,j=2
 79     => out[0]!=0,计数失败一次,k++;此时k=1,j=2
 80     => k++,for循环完成两次j++;此时k=2,j=3
 81     => out[2]!=0,计数失败一次,k++;此时k=3,j=3
 82     => 由于j==m,计数cnt++,cnt=7,输出out[3]=7,k++,j++;此时k=4,j=4
 83     => 跳出循环重新给j赋值,此时k=4,j=1
 84     => out[4]!=0,计数失败一次,k++;此时k=5,j=1
 85     => out[5]!=0,计数失败一次,k++;此时k=6,j=1
 86     => k++,for循环完成一次j++;此时k=7,j=2
 87     => k++,for循环完成两次j++;此时k=8,j=3
 88     => out[8]!=0,计数失败一次,k++;此时k=9,j=3
 89     => out[9]!=0,计数失败一次,k++,;此时k=10,j=3
 90     => 由于j==m,计数cnt++,cnt=8,输出out[10]=8
 91     => k++,k==11,到达数组极限,重新给k赋值,此时k=0
 92     => for循环完成三次j++,此时k=0,j=4
 93     => 跳出循环重新给j赋值,此时k=0,j=1
 94     => out[8]!=0,计数失败一次,k++;此时k=1,j=1
 95     => k++,for循环完成一次j++;此时k=2,j=2
 96     => out[2]!=0,计数失败一次,k++;此时k=3,j=2
 97     => out[3]!=0,计数失败一次,k++;此时k=4,j=2
 98     => out[4]!=0,计数失败一次,k++;此时k=5,j=2
 99     => out[5]!=0,计数失败一次,k++;此时k=6,j=2
100     => k++,for循环完成两次j++;此时k=7,j=3
101     => 由于j==m,计数cnt++,cnt=9,输出out[7]=9,k++,j++;此时k=8,j=4
102     => 跳出循环重新给j赋值,此时k=8,j=1
103     => out[8]!=0,计数失败一次,k++;此时k=9,j=1
104     => out[9]!=0,计数失败一次,k++;此时k=10,j=1
105     => out[10]!=0,计数失败一次
106     => k++,k==11,到达数组极限,重新给k赋值,此时k=0,j=1
107     => out[0]!=0,计数失败一次,k++;此时k=1,j=1
108     => k++,for循环完成一次j++;此时k=2,j=2
109     => out[2]!=0,计数失败一次,k++;此时k=3,j=2
110     => out[3]!=0,计数失败一次,k++;此时k=4,j=2
111     => out[4]!=0,计数失败一次,k++;此时k=5,j=2
112     => out[5]!=0,计数失败一次,k++;此时k=6,j=2
113     => k++,for循环完成一次j++;此时k=7,j=3
114     => out[7]!=0,计数失败一次,k++;此时k=8,j=3
115     => out[8]!=0,计数失败一次,k++;此时k=9,j=3
116     => out[9]!=0,计数失败一次,k++;此时k=10,j=3
117     => out[10]!=0,计数失败一次
118     => k++,k==11,到达数组极限,重新给k赋值,此时k=0,j=3
119     => out[0]!=0,计数失败一次,k++;此时k=1,j=3
120     => 由于j==m,计数cnt++,cnt=10,输出out[1]=10,k++,j++;此时k=2,j=4
121     ......最后一个数不一一列了
122     
123     https://blog.csdn.net/Dream_Weave/article/details/84940199?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight
124     这位大神的写的就比较一目了然,而且精简
125     */
原文地址:https://www.cnblogs.com/samgue/p/13246338.html