zoukankan      html  css  js  c++  java
  • 第七届湘计算机程序设计竞赛的学生 报道称,数字游戏

    报数游戏

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:2
    描写叙述
        n 个人站成一行玩一个报数游戏。全部人从左到右编号为 1 到 n。游戏開始时,最左边的人报 1。他右边的人报 2,编号为 3 的人报 3,等等。当编号为 n 的人(即最右边的人)报完 n 之后,轮到他左边的人(即编号为n-1 的人)报 n+1,然后编号为 n-2 的人报 n+2。以此类推。当最左边的人再次报数之后,报数方向又变成从左到右,依次类推。
        为了防止游戏太无聊,报数时有一个特例:假设应该报的数包括数字 7 或者是 7 的倍数。他应当用拍手取代报数。

    下表是 n=4 的报数情况(X 表示拍手)。

    当编号为 3 的人第 4 次拍手的时候。他实际上数到了 35。


     人  1  2  3  4  3  2  1  2  3
     报数  1  2  3  4  5  6  X  8  9
     人  4  3  2  1  2  3  4  3  2
     报数  10  11  12  13  X  15  16  X  18
     人  1  2  3  4  3  2  1  2  3
     报数  19  20  X   22  23  24  25  26  X
     人  4  3  2  1  2  3  4  3  2
     报数  X  29 30  31   32  33  34  X  36

        给定 n,m 和 k。你的任务是计算当编号为 m 的人第 k 次拍手时,他实际上数到了几。
    输入
    输入包括不超过 10 组数据。每组数据占一行。包括三个整数 n,m 和 k(2<=n<=100, 1<=m<=n, 1<=k<=100)。输入结束标志为 n=m=k=0。
    输出
    对于每组数据,输出一行。即编号为 m 的人第 k 次拍手时,他实际上数到的那个整数。
    例子输入
    4 3 1 
    4 3 2 
    4 3 3 
    4 3 4 
    0 0 0 
    例子输出
    17 
    21 
    27 
    35 
    来源

    湖南省第七届大学生计算机程序设计竞赛


    一道简单的模拟题:要模拟出现的情况,主要要推出一个规律  在边界的位置时,下一个报数的位置就是 2*n-2。(我也不知道是怎么推出来的)

    这样就能够推算出 每一个编号 下一个报数的位置;直接进行推断。

    #include <cstdio>
    #include <cstring>
    bool judge(int n)//推断函数,推断是否含7,或者是7的倍数
    {
         if( !(n % 7) ) return true;
         while(n)
        {
            if( n % 10 == 7 )
                return true;
            n /= 10;
        }
        return false;
    }
    int main()
    {
        int n,m,k,i;
        while(scanf("%d%d%d",&n,&m,&k)&&n&&m&&k)
        {
            int count=0;
            for(i=7;;i++)
            {
                if(judge(i))
                {
                    int x=i%(2*n-2);//得出的是初始编号
                    if(x==0)
                     x=2*n-2;
                    if(x==m || (x>=n && 2*n-x==m ))//符合题意的情况
                        count++;
                    if(count==k)
                        break;
                }
            }
            printf("%d
    ",i);
        }
        return 0;
    }
    

    还看到别人的还有一种思路,直接找到规律,依据规律暴力求解。

    分成了两个部分进行考虑,边界情况就直接是2*n-2,中间的间隔是两个数循环变化的。

    #include <cstdio>
    #include <iostream>
    using namespace std;
    bool is7( int n )//推断
    {
        if( !(n % 7) ) return true;
        while(n)
        {
            if( n % 10 == 7 ) return true;
            n /= 10;
        }
        return false;
    }
    int main()
    {
        int n, m, k;
        while( scanf("%d %d %d", &n, &m, &k) !=EOF && n+m+k )
        {
            int cnt = 0, period = 2 * n - 2;
            if( n == m || m == 1 )//边界的情况
            {
                for( int i = m; ; i += period ) if( is7( i ) )
                    {
                        cnt++;
                        if( cnt == k )
                        {
                            printf("%d
    ", i);
                            break;
                        }
                    }
            }
            else
            {
                int next = 2 - m;
                for( int i = m; ; swap( next, i ) )//中间的情况
                {
                    next += period;
    
                    if( is7( i ) )
                    {
                        cnt++;
                        if( cnt == k )
                        {
                            printf("%d
    ", i);
                            break;
                        }
                    }
                }
            }
        }
        return 0;
    }
    

    换一种思路。直接进行模拟,依照先顺序,后倒序进行模拟;

    #include <cstdio>
    #include <cstring>
    bool judge(int n)//推断
    {
         if( !(n % 7) ) return true;
         while(n)
        {
            if( n % 10 == 7 )
                return true;
            n /= 10;
        }
        return false;
    }
    int main()
    {
        int n,m,k,i;
        while(scanf("%d%d%d",&n,&m,&k)&&n&&m&&k)
        {
            int pos=0,count=0,flag=0;
            for(i=1;i<=n;i++)//顺序处理
            {
                pos++;
                if(i==m)
                {
                    if(judge(pos))
                        count++;
                    if(count==k)//搜索到结果了
                    {
                       printf("%d
    ",pos);
                       break;
                    }
                }
                if(i==n)
                {
                    i=n-1;//进行倒序处理
                    for(;i>=1;i--)
                    {
                        pos++;
                        if(i==m)
                        {
                            if(judge(pos))
                                count++;
                            if(count==k)
                            {
                                flag=1;
                                printf("%d
    ",pos);
                                break;
                            }
                        }
                    }
                 if(flag)  break;
                 i=1;//回溯到顺序
               }
            }
        }
        return 0;
    }
    


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    关于xcode 9.0数组问题的遇到的坑
    PHP将emoji表情进行过滤
    iOS 11更新后以及iPhone X推出后工程中遇到的问题及适配
    在IOS11中position:fixed弹出框中的input出现光标错位的问题
    采用腾讯云直播断流续播相关问题
    论坛灌水机与注册机问题
    以下内容对于灵活修改textField中文本以及占位文本属性进行了完整的封装,加入项目中可以节约开发时间。
    JS基础语法---总结
    JS基础语法---创建对象---三种方式创建对象:调用系统的构造函数;自定义构造函数;字面量的方式
    JS基础语法---编程思想和对象
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4843201.html
Copyright © 2011-2022 走看看