题意:
交互题,他会告诉你有一个只有 0 和 1 的数组的长度 n,接下来你有不多余15次操作:
“? str” ?是询问操作,str就是你认为这个数组的样子,他会返回里面错了多少个,继续循环,不能超过15次。
“! pos0 pos1”!是答案操作,pos0,pos1是你找到相邻 0 和 1 的的下标,结束循环。
题解:
不能超过 15 次操作并且长度不会超过 1000,说明就可以二分出只有 0 和 1 的两位区间。怎么判断区间有0和1呢?
当全取 0 的时候,得到的数就是区间内 1 的个数,同理,我们可以的到区间内 0 的个数。只要得到的数在全错和全对范围内就说明有 0 和 1 的存在,即:
答案:000101
000111 会得到 2,如果全错会得到 3 ,全对会得到 0,这时候 0 <= 2 <= 3,所以里面一定存在 0 和 1。
AC代码:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 1000+10;
int num1, n;
bool check(int l, int r) {
printf("? ");
for(int i = 0; i < l; i++) {
printf("0");
}
for(int i = l; i <= r; i++) {
printf("1");
}
for(int i = r + 1; i < n; i++) {
printf("0");
}
puts("");
fflush(stdout);
int num2;
cin >> num2;
if(num1 - (r - l + 1) < num2 && num2 < num1 + (r - l + 1)) {
return true;
} else {
return false;
}
}
int main() {
while(cin >> n) {
printf("? ");
for(int i = 0; i < n; i++) {
printf("0");
}
puts("");
fflush(stdout);
cin >> num1;
int l = 0, r = n - 1;
while(r - l >= 2) {
int mid = (l + r) >> 1;
if(check(mid, r)) {
l = mid;
} else {
r = mid;
}
}
printf("? ");
for(int i = 0; i < l; i++) {
printf("0");
}
printf("10");
for(int i = r + 1; i < n; i++) {
printf("0");
}
puts("");
fflush(stdout);
int temp;
cin >> temp;
if(num1 > temp) {
printf("! %d %d\n", r + 1, l + 1);
} else {
printf("! %d %d\n", l + 1, r + 1);
}
}
}