洛谷 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;
}