18063-圈中的游戏-(第九章第4题)-"数组指针的使用"-数学分析

代码借鉴CSDN大佬https://blog.csdn.net/weixin_41409140/article/details/88071047(对大佬的大佬代码进行分析)

18063 圈中的游戏

时间限制:1000MS  内存限制:65535K
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC;VC

Description

有n个人围成一圈,从第1个人开始报数1、2、3,每报到3的人退出圈子。编程使用链表找出最后留下的人。

输入格式

输入一个数n,1000000>=n>0 

输出格式

输出最后留下的人的编号

输入样例

3

输出样例

2

----------------------------------------------------------

思路:

/*#include <stdio.h>
#include<stdlib.h>
int c[1000000];
int main()
                                                          //注意了cur和pre是类似于指针,是一种咱们的“数组指针”,指向的是下标
int i,j,n,pre,cur;                                     //pre为搞死的那个的前一个的下标,cur为搞死那个的下标
scanf("%d",&n);
    if(n==1)printf("1 ");                          //只有一个人都数不了(不可以自己和自己数哦)(毕竟最后是一定要留一个人的就直接输出1就好(但是输入的如果是2的话,                                                             

                                                               是可以数的了,所以就是1死,二活,所以只有输入1的时候是一个特例,不要认为输入2的时候不够三个人就也是特例了
    else
    {
        for(i=0;i<n-1;i++) c[i]=i+1;               //这里外部循环的边界可以是n也可以是n-1,甚至循环2n也是可以的,因为最后一个无论循环多少次都会存在的,就好像就只有一个人一样,是不可以自己和自己数的,所以就输出1                                                                                                                                   但是如果边界比较小的话就不能保证都筛选完了,所以最好还是n-1以上的(因为一次外部里面就有三次小的循环,每次内部循   环就搞死一个,所以要留一个,也就意味着要搞死n-1个,

                                                                      所以就要n-1次外部循环才行的,所以外部循环可以是n-1次及以上的       

c[n-1]=0;                                       //就是为了方便循环(毕竟也是一个圈,最后一项一般都不是本身,一般都是为了配合圈的操作来定一个比较牛的值,来方便后续的圈操作的

        cur=n-1;
        for(i=0;i<n-1;i++)
        {
for(j=0;j<3;j++)
            {
               pre=cur;                                 //这个个循环里面其实pre就是记录之后cur指向的下标的的前一个下标的
                cur=c[cur];                            //核心
            }
            c[pre]=c[cur];                          //cur的数值给了pre的数值
        }
        printf("%d",pre+1);                     //由于初始化的时候是把第一项是2,第二项是3,所以要想得到最后的数值的话
                                                          //因为我们得到的是下标pre所以就要+1才是它的数值了
    }
    return 0;
}
*/

 

无注释代码

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 int c[1000000];
 4 int main()
 5 {
 6     int i,j,n,pre,cur;
 7     scanf("%d",&n);
 8     if(n==1)
 9         printf("1
");
10     else
11     {
12         for(i=0;i<n-1;i++)
13         c[i]=i+1;
14         c[n-1]=0;
15         cur=n-1;
16         for(i=0;i<n-1;i++)
17         {
18             for(j=0;j<3;j++)
19             {
20                 pre=cur;
21                 cur=c[cur];
22             }
23             c[pre]=c[cur];
24         }
25         printf("%d",pre+1);
26     }
27      return 0;
28 }
View Code
方法二:
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int cj(int n,int m)
 4 {
 5     int p=0;
 6     int i;
 7     for(i=2;i<=n;i++)
 8     {
 9         p+=(p+m)%i;//这个方法的话就不用单独的讨论n=1的情况了,因为在这个函数里面。如果n=1的话是不会进行循环里面的,也就是最后是会返回1的
10     }
11     return p+1
12 }
13 int main()
14 {
15     int n,m;
16     scanf("%d",&n);
17     m=3;
18      int ans;
19      ans=cj(n,m);
20      printf("%d",ans);
21 }
View Code

虽然方法一是很难想到的,没有像方法二那麽好理解的,但是这个方法是可以用在如果他是选的不是第1位的开始数的话就不行了呢
比如1139 约瑟夫环问题

1139 约瑟夫环问题
时间限制:500MS 内存限制:65536K
提交次数:157 通过次数:79

题型: 编程题 语言: G++;GCC
Description
约瑟夫(josephus)环是这样的:假设有n个小孩围坐成一个圆圈,并从1开始依次给每个小孩编上号码。老师指定从第s位小孩起从1开始报数,
当数到m时,对应的小孩出列,依次重复,问最后留下的小孩是第几个小孩?例如:总共有6个小孩,围成一圈,从第一个小孩开始,
每次数2个小孩,则游戏情况如下:
小孩序号:1,2,3,4,5,6
离开小孩序号依次为:2,4,6,3,1
最后获胜小孩序号:5

 

输入格式
每组输入是三个整数n,s,m。(1 <= n <= 30, 1 <= s <= n,1 <= m <= 10) ;


输出格式
对于每组输入,请输出最后留下小孩的序号。


输入样例
6 1 2


输出样例
5

 

/********这里就是m就不再是3了,所以就只用改变一下内层的for的边界即可了
然后是从s开始的话,由于上面的代码都是从1开始的,但是画图发现,从s开始的话,答案其实就是从1开始的答案再+(s-1)也就是s和1的差,因为是按序的编号的,所以是可以的
具体代码:********

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int c[30];
 4 int main()
 5 {
 6     int i,j,pre,n,cur,s,m;
 7     scanf("%d %d %d",&n,&s,&m);
 8     if(n==1)
 9     printf("1
");
10     else
11 12      for(i=0;i<n-1;i++)
13      c[i]=i+1;
14 15     c[n-1]=0;
16     cur=n-1;
17     for(i=0;i<=n-1;i++)
18     {
19       for(j=0;j<3;j++)
20       {pre=cur;
21       cur=c[cur];
22       }
23       c[pre]=c[cur];
24     }
25     printf("%d",pre+s);//由于板子里面的是pre+1.然后我们要上加s-1,所以1和-1抵消了,所以就是直接的就s+pre即可了
26 }*/
View Code
原文地址:https://www.cnblogs.com/SCAU-gogocj/p/11925922.html