果然签到题就是好玩
首先我们可以猜2次来猜出第一个字符是什么,后面的串就和这个字符没关系了。
假设剩下的三个字符是tmp[0]
,tmp[1]
,tmp[2]
,目前已知答案串的长度为
i
−
1
i-1
i−1的前缀是ans
。考虑第
i
i
i位(
i
≤
n
−
1
i\leq n-1
i≤n−1),我们可以在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
i−1就说明第
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;
}