[loj2863] [ioi2018 d1t1] combo - 有趣的交互题

传送门:https://loj.ac/problem/2863

斗胆来一发ioi题解。

今年的d1t1是一道交互题。喜欢出交互题是ioi的一大特色之一,而国内的正式比赛中还是很少见到交互题的身影的(印象中只有wc2016和wc2018有交互题)。

虽是ioi,但难度不算大的题还是会出现的,主要也是要考虑到世界各国选手的整体水平。本题算是今年6道题中最简单的一道,全场大约有一半的选手都成功ac。

题目大意:有一个字符串s,长度n<=2000,由4种字符“A”“B”“X”“Y”组成,保证第一个字符在后面不再出现。你可以向交互库询问一个自己指定的字符串p(p的长度不超过n*4且也是由上述4种字符组成),交互库会返回一个非负整数x,表示最长的、既是s的前缀、也是p的子串的串长。要求用不超过n+2次询问确定串s。

看到这个题,首先可以想到:这个奇怪的限制“保证第一个字符在后面不再出现”是干什么用的?容易想到我们可以用第一个字符作为“天然的分隔符”,在p串中一次性塞入若干可能的结果来进行猜测。

容易想到的一种解法是,如果已知长度为x的前缀(记做q),我们可以用2次操作,问出第x+1个字符:

首先令p=qAqB,如果询问结果=x+1,说明下一个字符是A或B,于是再询问p=qA,根据结果是x还是x+1就可以确定下一个字符;同样地,如果第一次询问得到x,说明下一个字符是X或Y,同样也可以再询问一次得到结果。

这样询问次数=2n,能不能更给力些?

要做到n+2次询问,说明我们要做到1次询问得到1位的结果,当然我们会发现问出第1位和最后一位的话两次询问是无法避免的。

首先,既然第一个字符不会重复出现,我们下面的询问就只是3选1,而不是4选1。下面不妨设首位是Y,后面的可选项是A,B,X吧。

然后,我们相当于每次要构造一个p,使得可能会有3种不同的回答,分别对应下一个字符的3种情况。

3种回答显然只能是x,x+1,x+2,因为x-1之类的回答没有任何意义。

我们可以让p中有一个qA,用x+1表示A,然后不加入形如qB的串,则x就是B,那x+2呢?

如果要让X时答案是x+2,就意味着必须在qX后面再匹配一位,而后一位我们不知道,咋办?

此时我们就要利用|p|<=4n的性质。直接枚举下一位!

也就是说,p=qAqBAqBBqBC,此时恰好满足我们的要求。

于是问题被完美解决了。干得漂亮!

//注:以下代码根据ioi提交格式编写

#include<bits/stdc++.h>
using namespace std;
#include"combo.h"
string as,p;
void wk(char a,char b,char c,int n){
	for(int i = 2;i < n;++i){
		p = as + a + as + b + a + as + b + b + as + b + c;
		int j = press(p);
		if(j == i - 1) as += c;
		else if(j == i) as += a;
		else as += b;
	}
	if(press(as + a) == n) as += a;
	else if(press(as + b) == n) as += b;
	else as += c;
}
string guess_sequence(int n){
	if(press("AB")){
		if(press("A")) as = "A";
		else as = "B";
	}
	else{
		if(press("X")) as = "X";
		else as = "Y";
	}
	if(n == 1) return as;
	if(as == "A") wk('B','X','Y',n);
	else if(as == "B") wk('A','X','Y',n);
	else if(as == "X") wk('A','B','Y',n);
	else wk('A','B','X',n);
	return as;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值