[IOI2018]组合动作 题解

传送门 LOJ2863

果然签到题就是好玩

首先我们可以猜2次来猜出第一个字符是什么,后面的串就和这个字符没关系了。

假设剩下的三个字符是tmp[0]tmp[1]tmp[2],目前已知答案串的长度为 i − 1 i-1 i1的前缀是ans。考虑第 i i i位( i ≤ n − 1 i\leq n-1 in1),我们可以在ans串后面接上一个字符然后press来检查有没有获得更多的金币,但是这样的话你总共要press大约 3 n 3n 3n次,不够理想。

我们可以设计一种方法来一次就获得S[i]是什么字符,那就需要设计一个串p使得对于不同的S[i]press(p)的返回值不同。我们可以令p=ans+tmp[0]+ans+tmp[1]+tmp[0]+ans+tmp[1]+tmp[1]+ans+tmp[1]+tmp[2],那么如果press(p)返回的是 i − 1 i-1 i1就说明第 i i i位是tmp[2],如果返回值是 i i i就说明第 i i i位是tmp[0],否则就是tmp[1]

对于最后一位,再press两下就行了。

#include "combo.h"
#include <string>

char tmp[3];
std::string guess_sequence(int n) {
	char first;
    if (press("AB")) {
		if (press("A")) first = 'A', tmp[0] = 'B', tmp[1] = 'X', tmp[2] = 'Y';
		else first = 'B', tmp[0] = 'A', tmp[1] = 'X', tmp[2] = 'Y';
	} else {
		if (press("X")) first = 'X', tmp[0] = 'A', tmp[1] = 'B', tmp[2] = 'Y';
		else first = 'Y', tmp[0] = 'A', tmp[1] = 'B', tmp[2] = 'X';
	}
	std::string ans; ans += first;
	if (n == 1) return ans;
	for (int i = 2; i < n; ++i) {
		std::string p = ans + tmp[0] + ans + tmp[1] + tmp[0] + ans + tmp[1] + tmp[1] + ans + tmp[1] + tmp[2];
		int coin = press(p);
		if (coin == i - 1) ans += tmp[2];
		else if (coin == i) ans += tmp[0];
		else ans += tmp[1];
	}
	if (press(ans + tmp[0]) == n) ans += tmp[0];
	else if (press(ans + tmp[1]) == n) ans += tmp[1];
	else ans += tmp[2];
	return ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值