题目链接:
题意:
一道交互题,给你一个n,代表字符串长度,让你询问不超过2n次子串,若回答1代表是子串,0代表不是子串,每次询问的子串长度不能超过n
思路:
首先一定可以在2n次询问中得到答案串
下面给出做法:
若n == 1,直接询问0和1即可
否则,我们先询问01,10,00,11,这四个里肯定至少有一个是存在的,在得到其肯定答复后,我们继续向右询问,拿01来说吧,我们继续询问010,011,直到向右加0或1的情况都得到否定答复,我们再反过来向左询问
这样做能保证询问次数不超过2n次
注意:
交互题的格式,每次询问后需要cout.flush(),输出最终答案后也要cout.flush()
代码:
#include<bits/stdc++.h>
using LL = long long;
void solve(){
// I know you are here
// Thank you for your appreciation
int n;
std::cin >> n;
int x;
if(n == 1) {//这里是n为1时的情况
std::cout << "? " << '1' << "\n";
std::cout.flush();
std::cin >> x;
if(x == 1) std::cout << "! " << '1' << "\n";
else std::cout << "! " << '0' << "\n";
std::cout.flush();
return;
}
//下面是n大于1时的情况
std::vector<std::string> s(4);
s[0] = "01";
s[1] = "10";
s[2] = "11";
s[3] = "00";
std::string ans;//代表最终答案
int cnt = 2;//代表目前已经能够确定的答案长度,防止询问的长度大于n
for(auto it: s) {
std::cout << "? " << it << "\n";
std::cout.flush();
std::cin >> x;
if(x == 1) {
ans = it;
if(cnt == n) break;//答案长度已经为n
while(1) {//一直向右
if(cnt == n) break;//答案长度已经为n
bool ok = false;
std::string a = ans + '0';
std::string b = ans + '1';
std::cout << "? " << a << "\n";
std::cout.flush();
std::cin >> x;
if(x == 1) {
cnt++;
ans += '0';
ok = true;
}
if(ok) continue;//一定要有这句,否则可能询问超过2n次
std::cout << "? " << b << "\n";
std::cout.flush();
std::cin >> x;
if(x == 1) {
cnt++;
ans += '1';
ok = true;
}
if(!ok) break;//已无法向右
}
if(cnt == n) break;//答案长度已经为n
while(1) {//一直向左,和上面类似
if(cnt == n) break;
bool ok = false;
std::string a = '0' + ans;
std::string b = '1' + ans;
std::cout << "? " << a << "\n";
std::cout.flush();
std::cin >> x;
if(x == 1) {
cnt++;
ans = '0' + ans;
ok = true;
}
if(ok) continue;
std::cout << "? " << b << "\n";
std::cout.flush();
std::cin >> x;
if(x == 1) {
cnt++;
ans = '1' + ans;
ok = true;
}
if(!ok) break;
}
break;
}
}
std::cout << "! " << ans << "\n";
std::cout.flush();//输出答案后要输出这句
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);std::cout.tie(0);
int _;
std::cin >> _;
while(_--){
solve();
}
return 0;
}