[C#]有n个小孩排成一圈。从第1个小孩开始作1至3报数,凡报数3的小孩从圈中出来,求最后出圈的小孩的顺序号是多少?

来源:互联网 发布:淘宝怎么截图返现 编辑:程序博客网 时间:2024/06/02 14:51

网上很多类似的文章,但大致都是用C语言做的,这里就以C#语言做的!

稍做改变,我们以5个人,依次报数1234,报4的离开进行分析。

5个人对应5个编号,也就是编号1,2,3,4,5,最后留下来的人是留下来的编号,这个不要弄晕了。
然后给每一个人一个索引,索引从1开始,那么5个人分别对应的索引也就s[1],s[2]...
那么我们也就知道编号4对应的索引也就是4了,开始是从编号1开始报数的,编号1对应的索引也是1,
那么我们就把每一轮报数为1的索引定义为num,也就是num=1


第一轮:编号4报的是数字4,而编号4对应的索引也就是4,报4的出去,那么后面编号5也就
填充到s[4]的位置了,那么接下来报1的人也就是编号5了,编号5对应的索引此时是4,也就
是num=4


第二轮:编号5开始报1,转到报4时就是编号3了,编号3对应的索引还是3,此时编号3也就要
出去了,后面的又要往前面填了,编号3后面的也就是编号5了,还是编号5开始报数,此时编
号5对应的索引也就是3,也就是num=3,s[3]=编号5


第三轮:此时留下的人只剩编号1,2,5了,编号5开始报1,报到4的时候是编号5,那么编
号5移除掉,那么接下来报1的也就是编号1了,也就是num=1


第四轮:编号1开始报1,很明显报到4的也就是编号2了,那么结果留下来的就是编号1了。


通过上面规律,不难发现,在没开始报数时,num=1,第一轮结束,num=4,人数=4人,
第二轮:num=3,人数3人,第三轮:num=1,人数2
  因此得到的公式是:num=(num+4-1)%当前人数
测试下看是不是:num=1时,当前人数5人,输出num=4,也就是接下来报1的人是索引4
对应的编号,也就是编号5了,因为编号4已经移除掉了,再进行第二轮时,此时num=4,当前人数4人,输出的num=3,
也就是索引为3的编号3退出了,此时现在就剩下编号1,2,5,那么编号5现在对应的索引是几多勒?
(答案是:3),那么接下来报1的是编号几勒?(答案是编号5,也就是索引3),此时num=3
第三轮:num=3,人数为3人,输出的num=6%3=0,发现没有余数?怎么办?问题又来了:


例:编号1,2,3,4依次报数1234,报4的出去
num= (1+4-1)/4=0,出去的人是编号4,而接下来报1的也就是编号1了,也就是num要等于1,
于是我又发现规律了,当没有余数时,也就是num=0时,我把num=当前人数,再测试下看看,
编号4出去前,当前人数为4,把num=4赋值,进入下一次,此时人数是3人,num=(4+4-1)%3=1,也就是
接下来报1的编号是索引1对应的编号了,也就是编号1....



认真思考的话,看到这里,你可能明白了点吧,注意的是,每移除一个编号时,后面的人的编号对应的索引都-1了,
就好比最先开始s[4]=编号4,s[5]=编号5,编号4移除去后,此时s[4]也就是编号5了...



再提最后一点,每轮的索引num对应的编号是开始数1的人!


晕了的话就慢慢体会吧,要是这还看不懂?再看3遍,还看不懂,你拿刀砍我吧!


分析就到这里,下面是代码,可对照代码再分析分析!!!


   int j, k = 1, total = 5, start = 1, alter = 4;
            int[] count = new int[total + 1];
            int[] s = new int[total + 1];
            for (int i = 1; i <= total; i++)
            {
                s[i] = i;
            }
            
            for (int i = total; i >= 2; i--)
            {
                start = (start + alter - 1) % i;
                if (start == 0)
                {
                    start = i;
                }
                count[k] = s[start];
                k++;
                for (j = start + 1; j < i; j++)
                {
                    s[j - 1] = s[j];
                }

            }
            count[k] = s[1];
            Console.WriteLine("最后一个留在圈里的小孩编号是:{0}", count[k]);