洛谷 U85556 教官的游戏

洛谷 U85556 教官的游戏

洛谷传送门

题目背景
SeawaySeaway和iamrjjiamrjj一起被万恶的分班考试分到了高一 · 66班,当然了,他们要参加军训。在训练场上,教官带66班玩了个小游戏......

题目描述
有这样的一个经典小游戏:大家从11开始依次数数,数到77的倍数或者数字中带77的数就拍手。而教官的游戏是这样的:因为我们是66班,所以数到66的倍数或者数字中带66的数就喊“报告!”,这个倒霉蛋要被淘汰。教官还说,他要奖励最后剩下的同学。SeawaySeaway和iamrjjiamrjj顿时摩拳擦掌,而他们都想到编程解决这个问题。但是...训练场没有电脑啊!所以他们俩偷偷地找到了你,希望你告诉他,他们站到哪个位置能赢。(假设他们俩是一个人)

输入格式
输入文件包括一个整数NN,表示高一 · 66班一共有NN个同学。

输出格式
输出文件包括一个整数PP,表示SeawaySeaway和iamrjjiamrjj站的位置。

输入输出样例
输入 #1 复制
7
输出 #1 复制
1
说明/提示
数据范围: 1\le N \le 10^51≤N≤10
5

题解:

这是一道模拟的题。

我们分析题意,题目是在问这样一个问题:\(N\)个人站圈数数,数到能被6整除的数或者含6的数就被淘汰,其他人继续数。问最后剩下的人的位置。

那么我们很容易想到用模拟解这个问题(其实确实没有什么更容易理解的算法)。那么我们试着手敲代码就会发现一些比较难处理的点:

怎么维护有人淘汰后的队列?

怎么维护圈形队列?

怎么判断数中的每位是否含6?

我们知道,题目的队列是圈形,那么我们就可以用一种手段反复遍历这个圆(用一个pos变量表示位置,每次循环pos++,如果>n(加冒了),就从1开始)。这时再借助一个v数组表示有没有被淘汰,如果没有,就持续累加tot(即这个人数的数)。然后再判断是否合法。

判断是否合法这里可以用一个外置函数来进行。首先判能否被6整除。如果不能再判各位有没有6,这个也很简单,大家学习过数字各位分割,其实和那个的原理是一样的,每次/10就能“干掉”最后一位,然后再模上10看看余数是不是6即可。

所以这题就能这样的A过去。

模拟是最简单最朴素同时也是最考人的算法(个人觉得)。这种算法考的是OIer们代码实现思路的能力,这也是之后的学习中最重要的能力之一。

(所以这道题被我评成了普及+/提高-的绿题)

代码:

#include<cstdio>
using namespace std;
int n,pos,tot,last,cnt;
int v[100001];
bool check(int x)
{
    if(x%6==0)
        return 1;
    while(x)
    {
        if(x%10==6)
            return 1;
        x/=10;
    }
    return 0;
}
int main()
{
    scanf("%d",&n);
    while(1)
    {
        pos++;
        if(pos>n)
            pos=1;
        if(v[pos]==0)
        {
            tot++;
            if(check(tot))
            {
                last=pos;
                v[pos]=1;
                cnt++;
            }
            if(cnt==n)
                break;
        }
    }
    printf("%d",last);
    return 0;
}
posted @ 2019-08-29 17:11  Seaway-Fu  阅读(64)  评论(0编辑  收藏  举报