• 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
  • 相关阅读:
    今日总结
    每日总结
    每日总结
    每日总结
    重返现世
    [PKUWC2018]随机游走
    [HAOI2015]按位或
    [NOI2020] 超现实树
    [NOI2017] 游戏
    [CSACADEMY]Card Groups
  • 原文地址:https://www.cnblogs.com/SCAU-gogocj/p/11925922.html
Copyright © 2020-2023  润新知