题目链接:http://codeforces.com/problemset/problem/1011/D
题目让你在1到m之间猜一个数x,你每猜一个数,会得到三种回复,-1(x < y) ,0(x == y), 1 (x > y)。
而且每次回答都不一定是正确的回答,会根据一个序列 p,0为错误回答,1为正确回答,的规律回复你。
首先需要确定序列p,这里的方法是问 n次 数字1来得到回复,因为1已经是最小的数字,如果他回复是-1,可以充分说明当前的回答是错误的,以此得到序列p。
其次需要特别注意一句话:如果正确答案是t,只要回复的是t,那么这个答案就是正确的,如果回答是-t,那么这个答案就是错误的,这句话说明无论当前回答的是正确还是错误的答案,如果回复的是0,那么答案就是0。
在二分是的时候,不要因为因为当前答案是错误的就跳过不考虑,我们同样可以利用这个错误的答案。
如果当前回复的答案是错误的,为-1,那么可以说明 x >= y,其他情况也同理,但是这里可以直接写成 x > y,等于的情况可以去掉,因为上面提到如果相等的话,回答一定会是0而不是-1。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int Maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
bool p[60];
int main(void)
{
int n, m, ans;
scanf("%d%d", &n, &m);
memset(p, true, sizeof(p));
for(int i = 0; i < m; ++i) {
cout << 1 << endl;
scanf("%d", &ans);
if(ans == 0) return 0;
if(ans == -1) p[i] = false;
}
int L = 1, R = n, mid, cur = 0;
while(1) {
mid = (ll)(L+R)/2;
cout << mid << endl;
scanf("%d", &ans);
if(ans == 0) break;
if(!p[cur]) {
if(ans == -1) L = mid+1;
else if(ans == 1) R = mid-1;
} else {
if(ans == -1) R = mid-1;
else if(ans == 1) L = mid+1;
}
cur = (cur+1)%m;
}
return 0;
}