【刷题】LOJ 2863 「IOI2018」组合动作
题目描述
你在玩一个动作游戏。游戏控制器有 \(4\) 个按键,A
、B
、X
和 Y
。在游戏中,你用组合动作来赚金币。你可以依次按这些按键来完成一个组合动作。 这个游戏有一个隐藏的按键序列,可以表示为由这 \(4\) 个字符组成的串 \(S\) 。你并不知道这个串 \(S\) ,但是你知道它的长度为 \(N\) 。
你还知道,\(S\) 的首字符不会在串中重复出现。 例如,\(S\) 可以是“ABXYY
”或者“XYYAA
”,但不能是“AAAAA
”或“BXYBX
”。
你可以依次按最多 \(4N\) 个按键来完成一个组合动作。串 \(p\) 为你所按的按键序列。你用这个组合动作赚到的金币数量,等于同时为 \(p\) 之子串和 \(S\) 之前缀的最长字符串的长度。串 \(t\) 的子串定义为 \(t\) 中的连续字符序列(可以为空)。\(t\) 的前缀定义为 \(t\) 的子串,其或者为空,或者包含 \(t\) 的首字符。
例如,如果 \(S\) 是“ABXYY
”,而 \(p\) 是“XXYYABYABXAY
”,你会得到 \(3\) 个金币,因为“ABX
”是可作为 \(p\) 的子串的 \(S\) 的前缀中最长的。
你的任务是,用少量的组合动作,找出隐藏字符串 \(S\) 。
输入格式
你需要实现下面的函数:
string guess_sequence(int N)
N
:串 \(S\) 的长度。- 对每个测试用例,该函数被调用恰好一次。
- 该函数应返回串 \(S\) 。
你的程序可以调用下面的函数:
int press(string p)
p
:你的按键序列。p
必须是长度为从 \(0\) 到 \(4N\) 的串(包括 \(0\) 和 \(4N\))。p
的每个字符必须是A
、B
、X
或者Y
。- 对每个测试用例,你调用该函数的次数不能超过 \(8\ 000\) 次。
- 该函数的返回结果是,当按出按键序列
p
后你赚到的金币数量。
如果不满足上面的条件,你的程序将被判为 Wrong Answer
。否则,你的程序将被判为 Accepted
,而你的得分将根据 press
的调用次数来计算(参见子任务)。
样例
设 \(S\) 为“ABXYY
”。评测程序调用了 guess_sequence(5)
。数据交互过程的例子如下所示:
调用 | 返回值 |
---|---|
press("XXYYABYABXAY") |
$3$ |
press("ABXYY") |
$5$ |
press("ABXYYABXYY") |
$5$ |
press("") |
$0$ |
press("X") |
$0$ |
press("BXYY") |
$0$ |
press("YYXBA") |
$1$ |
press("AY") |
$1$ |
对于 press
的第 \(1\) 次调用,“ABX
”是“XXYYABYABXAY
”的子串,而“ABXY
”不是,因此返回 \(3\)。
对于 press
的第 \(3\) 次调用,“ABXYY
”本身是“ABXYYABXYY
”的子串,因此返回 \(5\)。
对于 press
的第 \(6\) 次调用,除了空串以外没有“ABXYY
”的其他前缀可以是“BXYY
”的子串,因此返回 \(0\)。
最后,guess_sequence(5)
应当返回“ABXYY
”。
附件压缩包中的文件 sample-01-in.txt
对应于本例。
数据范围与提示
- \(1\le N\le 2\ 000\)
- 串 \(S\) 的每个字符必须是
A
、B
、X
或Y
。 - \(S\) 的首字符不会再 \(S\) 中重复出现。
在本题中,评测程序不是适应性的。意思是说,在评测程序开始运行的时候 \(S\) 就固定下来,而且不依赖于你的程序所做的询问。
子任务
- (5分)\(N=3\)
- (95分)没有附加限制。对该子任务,你在每个测试用例上的得分将计算如下。设 \(q\) 为调用
press
的次数。- 如果 \(q\le N+2\),你的得分为 \(95\)。
- 如果 \(N+2<q\le N+10\),你的得分为 \(95-3(q-N-2)\)。
- 如果 \(N+10<q\le 2N+1\),你的得分为 \(25\)。
- 如果 \(\max\{N+10,2N+1\}<q\le 4N\),你的得分为 \(5\)。
- 否则,你的得分为 \(0\)。
注意,你在每个子任务上的得分,等于你在该子任务下所有测试用例上的最低得分。
评测程序示例
评测程序示例将读取如下格式的输入:
- 第 \(1\) 行:\(S\)
如果你的程序被判为 Accepted
,评测系统示例将打印出 Accepted: q
,这里 q
为函数 press
的调用次数。
如果你的程序被判为 Wrong Answer
,它打印出 Wrong Answer: MSG
。各类 MSG
的含义如下:
invalid press
:输入到press
的值p
是无效的。也就是说,p
的长度不在 \(0\) 到 \(4N\) 之间(含 \(0\) 和 \(4N\)),或者p
的某些字符不是A
、B
、X
和Y
。too many moves
:函数press
的调用次数超过 \(8\ 000\) 次。wrong guess
:guess_sequence
返回的不是 \(S\)。
题解
首先搞定第一个字母。先查询 AB
或XY
,然后就知道首字母是哪两个中的一个,再查询一次就好了。使用次数 \(2\) 次
然后考虑我们假设确定的字符串为 S
怎么知道下一位。我们可以考虑让剩下三个字母在询问中通过增加不同的贡献表现出来。这样构造,S+p[1]+S+p[2]+p[1]+S+p[2]+p[2]+S+p[2]+p[3]
,其中p[i]
是除了首字母外的其它字母。这样构造的好处就是,如果下一位是p[1]
,那么会多 \(1\) 的贡献,如果是p[2]
,会多 \(2\) 的贡献,否则多出的贡献为 \(0\) 。这样就可以把每一位给问出来。但是最后一位因为长度限制,问不了那么长的字符串,那么就只问到 \(n-1\) 位就好了。使用次数 \(n-2\) 次
最后一位采取与第一位相同的方法问出来就好了。使用次数 \(2\) 次
最后总共使用次数 \(2+n-2+2=n+2\) 次,正好
#include<bits/stdc++.h>
#include "combo.h"
using namespace std;
string guess_sequence(int n)
{
string s="",p[4];
int coins=0;
coins=press("AB");
if(coins)s=press("A")?"A":"B";
else s=press("X")?"X":"Y";
if(s=="A")p[1]="B",p[2]="X",p[3]="Y";
if(s=="B")p[1]="A",p[2]="X",p[3]="Y";
if(s=="X")p[1]="A",p[2]="B",p[3]="Y";
if(s=="Y")p[1]="A",p[2]="B",p[3]="X";
if(n==1)return s;
for(register int i=2;i<=n-1;++i)
{
coins=press(s+p[1]+s+p[2]+p[1]+s+p[2]+p[2]+s+p[2]+p[3]);
if(coins==i)s=s+p[1];
else if(coins==i-1)s=s+p[3];
else s=s+p[2];
}
coins=press(s+p[1]);
if(coins==n)s=s+p[1];
else
{
coins=press(s+p[2]);
if(coins==n)s=s+p[2];
else s=s+p[3];
}
return s;
}
【刷题】LOJ 2863 「IOI2018」组合动作的更多相关文章
- @loj - 2865@ 「IOI2018」狼人
目录 @description@ @solution@ @accepted code@ @details@ @description@ 在日本的茨城县内共有 N 个城市和 M 条道路.这些城市是根据人 ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
- Loj 3058. 「HNOI2019」白兔之舞
Loj 3058. 「HNOI2019」白兔之舞 题目描述 有一张顶点数为 \((L+1)\times n\) 的有向图.这张图的每个顶点由一个二元组 \((u,v)\) 表示 \((0\le u\l ...
- LOJ #6436. 「PKUSC2018」神仙的游戏(字符串+NTT)
题面 LOJ #6436. 「PKUSC2018」神仙的游戏 题解 参考 yyb 的口中的长郡最强选手 租酥雨大佬的博客 ... 一开始以为 通配符匹配 就是类似于 BZOJ 4259: 残缺的字符串 ...
- LOJ #6435. 「PKUSC2018」星际穿越(倍增)
题面 LOJ#6435. 「PKUSC2018」星际穿越 题解 参考了 这位大佬的博客 这道题好恶心啊qwq~~ 首先一定要认真阅读题目 !! 注意 \(l_i<r_i<x_i\) 这个条 ...
- LOJ #6432. 「PKUSC2018」真实排名(组合数)
题面 LOJ #6432. 「PKUSC2018」真实排名 注意排名的定义 , 分数不小于他的选手数量 !!! 题解 有点坑的细节题 ... 思路很简单 , 把每个数分两种情况讨论一下了 . 假设它为 ...
- loj#2012. 「SCOI2016」背单词
题目链接 loj#2012. 「SCOI2016」背单词 题解 题面描述有点不清楚. 考虑贪心 type1的花费一定不会是优的,不考虑, 所以先把后缀填进去,对于反串建trie树, 先填父亲再填儿子, ...
- loj#2718. 「NOI2018」归程
题目链接 loj#2718. 「NOI2018」归程 题解 按照高度做克鲁斯卡尔重构树 那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离 s ...
- [LOJ 2070] 「SDOI2016」平凡的骰子
[LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...
随机推荐
- C#宣告一个变量
在C#程序里,宣告一个变量,是件很容易的事情.如下面,宣告一个变量,并赋值: ; Console.WriteLine(type); bool type1 = false; Console.WriteL ...
- HAProxy 日志输出及配置
正所谓,没有软件敢说没有bug,人无完人,software is not perfect software.是软件就可能存在bug,那么如果出现bug,我们就要分析对我们业务的影响及可能如何避免bu ...
- apache工作模式总结及网站访问缓慢处理记录
apache目前主要有两种模式:prefork模式和worker模式:1)prefork模式(默认模式)prefork是Unix平台上的默认(缺省)MPM,使用多个子进程,每个子进程只有一个线程.每个 ...
- 函数:this & return、break、continue、exit()
this this:的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象在调用的时候才能决定,谁调用的就指向谁. 情景1:指向 ...
- ACM注意事项
acm竞赛中不能使用一些屏幕控制和键盘读取的函数,如:getch(),geche(),gotoxy(),clrscr(),另外fflush(stdio)这个函数也不能使用,因为在有的编译 ...
- Visual Studio2015安装过程以及单元测试
安装环境: 安装版本: Visual Studio2015 安装过程: 因为我是在第一次老师安排的作业的时候感觉VC++6.0不如VS方便所以才装的Visual Studio2015,又安装了点插件, ...
- 个人阅读作业2:结合《No Silver Bullet》谈谈我在软件开发过程的遇到的困难与体会
英文捉急,只能挑一段看得比较懂的,而且正好和我们现在编程任务联系比较紧密的内容来谈一谈体会. 在<No Silver Bullet>中,作者描述了造成软件本质性困难(essence)的四个 ...
- Beta版本发布报告
项目名称 学霸系统写手机客户端 项目版本 Beta版本 负责人 北京航空航天大学计算机学院 hots团队 联系方式 http://www.cnblogs.com/hotsbuaa/ 要求发布日期 20 ...
- Linux内核第六节 20135332武西垚
如何描述一个进程:进程描述符的数据结构: 如何创建一个进程:内核是如何执行的,以及新创建的进程从哪里开始执行: 使用gdb跟踪新进程的创建过程. 进程的描述 操作系统三大功能: 进程管理(最核心最基础 ...
- Oracle系列(三): 情景查询一 a表中有个fid字段,逗号分隔开来,b表中有id字段及其他信息,如何关联a表的fid和和b表的id字段查询
现在有两个表,表a中 DOC FID 1 a,b,c 2 a,c,d 表b中 ID KEY a A b B c C d D 怎么联合查询出 DOC FID KEY 1 a,b,c A,B,C 2 a, ...