建议访问原文出处,获得更佳浏览体验。
原文出处:https://hyp1231.github.io/2018/07/28/20180728-cf1010b/
题意
交互式题目,通过和机器的沟通猜一个正整数
x (x≤m)
x
(
x
≤
m
)
。
每次你询问一个正整数
y (y≤m)
y
(
y
≤
m
)
,机器理应返回的正确答案为
⎧⎩⎨⎪⎪⎪⎪−101x<yx=yx>y
{
−
1
x
<
y
0
x
=
y
1
x
>
y
但是机器有些故障,他有时返回和正确答案互为相反数的结果,这个规律通过长度为
n
n
的数列 描述。数列
p
p
的每一项是 或者是
0
0
。对于第 次询问,如果数列的第
(k−1)(modn)+1
(
k
−
1
)
(
mod
n
)
+
1
项是
0
0
,则返回相反的答案;否则返回正确答案。
现在你可以给出最多 次询问,根据机器返回的值确定这个要猜测的数字
x
x
。
链接
题解
考虑询问为 时,正确答案只能为
1
1
或 。由于
n
n
不超过 ,因此我们的前
30
30
次询问可以全部为
y=1
y
=
1
,这样就可以知道数列
p
p
的每一项的值。
自此,机器返回的每个结果都可以根据数列 的值进行调整,可以确保得到正确信息。因此我们只需要在
1∼m
1
∼
m
之间二分,即可在剩余
30
30
步内得到
x
x
的值。()
代码
#include <iostream>
const int N = 32;
int n, m;
int p[N];
int ask(int a) {
std::cout << a << std::endl;
fflush(stdout);
int tmp;
std::cin >> tmp;
return tmp;
} // 询问 a,return 机器的返回值
void solve(int l, int r, int cur) {
int mid = (l + r) >> 1;
int ans = ask(mid) * p[cur % n];
if (ans == 0) exit(0);
else if (ans == -1) solve(l, mid, cur + 1);
else solve(mid + 1, r, cur + 1);
} // 第 cur 次询问
int main() {
std::cin >> m >> n;
for (int i = 0; i < n; ++i) {
p[i] = ask(1);
if (p[i] == 0) exit(0); // 如果正确答案就是 1,退出程序
}
solve(1, m, 0);
return 0;
}