Codeforces 1011D
题意:
有一个数字要猜,假设为$x$;给计算机的数假设为$y$,会得到以下三种回答:
若 $x<y$,回答 $−1$;
若 $x=y$,回答$0$;
若 $x>y$,回答 $1$;
但是,现在计算机坏了,对于某些询问会“说谎”;所谓“说谎”就是该回答 $−1$ 的回答了$1$ ;反之,该回答 $1$ 的回答了 $−1$。
抽象为 $01$ 字符串,$0101$ 表示第 $1$ 、$3$ 次询问计算机会“说谎”;若询问的次数大于了 $4$,就会循环;即第 $5、7$ 次会“说谎”。 (hack点)
现在,给这个 $01$ 串的长度 $n$,以及 $x$ 的最大范围 $m$(即 $x≤mx≤m$)。
还要求询问次数最多不超过 $60$ 次。
考虑到$n$只有$30$,所以前$n$次询问$1$骗取 $01$字符串,即询问$1$若回答不是$0$,则都应该是$1$,但是如果是$-1$,则说明当前说谎,记录一下。然后之后二分询问就好,注意若询问的次数大于了$n$,就会循环,Hack点
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#define ms(i, j) memset(i, j, sizeof i)
#define LL long long
#define db double
using std::cout;
using std::cin;
using std::endl;
int m, n, a[100];
void clean() {
}
int solve() {
clean();
cin >> m >> n;
for (int i = 1; i <= n; i++) {
cout << 1 << endl;
int whw; cin >> whw;
if (whw == 0) {
cout << 1 << endl;
exit(0);
} else a[i] = (whw == 1 ? 0 : 1);
}
int l = 1, r = m + 1;
int i = 1;
while (l <= r) {
//printf("i=%d, a[i]=%d\n",i, a[i]);
int mid = (l + r) >> 1;
cout << mid << endl;
int whw; cin >> whw;
if (whw == 0) {
cout << mid << endl;
exit(0);
}
if (a[i]) whw = (whw == -1 ? 1 : -1);
if (whw == 1) {
l = mid + 1;
} else r = mid;
i++;
if (i > n) i = 1;
}
exit(0);
return 0;
}
int main() {
solve();
return 0;
}