The hat

The hat

Created by LXC on Thu Feb 8 23:07:57 2024

https://codeforces.com/problemset/problem/1019/B

ranting: 2000

tag: binary search, interactive

problem

这是一道交互题。

一共有 $n$ 个人做成一圈,他们的编号从 $1$ 到 $n$。

现在每个人的手里面都有一个数字 $a_i$ ,并且保证每个人与他周围两个人的数字差为 $1$ ,即 $\mid a_i-a_{i\pm 1}\mid =1$ ,特别地,编号为 $1$ 与 $n$ 的人也满足这个规则。

在这个圈里面,编号为 $i$ 的人的对面坐着的是编号为 $i+\frac{n}{2}$ 的人(其中 $i\le \frac{n}{2}$),现在要你找到哪个人与他对面坐着的那个人手中的数字一样。

在最开始,交互程序会给你一个 $n(2\mid n, n\le 10^5)$ ,表示这个圈里面的人数,然后你可以输出以下两种格式的操作:

  1. ? x 表示你想询问位置为 $x$ 的人手中的数字,询问不可执行超过 $60$ 次;
  2. ! x 表示你的程序的答案,即满足 $a_x=a_{x+\frac{n}{2}}(x\le \frac{n}{2})$ ,特别地,如果找不到答案,则输出 ! -1

对于操作 $1$ ,交互程序会输出一个整数 $a_x$ 表示 $x$ 编号的人手中的数字。

对于操作 $2$ ,如果你的答案是错误的,程序会直接退出,且测试结果为 Wrong Answer ,否则若无其他问题则测试结果为 Accepted

solution

设$a_i - a_{i+\frac{n}{2}} = b_i$,可知$b_i = -b_{i+\frac{n}{2}}$,并且$b_i-b_{i+1} \in \lbrace -2, 0, 2\rbrace $,我们只需要找到$b_i = 0$的i即可

当存在$b_i$为奇数,所有$b_i$都为奇数。不存在答案。

否则一定存在答案,犹豫$b_i = x, b_{i+\frac{n}{2}} = -x$,在x为偶数的情况下从x到-x每次歩长为2,必定经过0。

$b_1$与$b_{1+\frac{n}{2}}$异号,从1到n/2之间进行二分查找一定能找到0

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

#include <bits/stdc++.h>
#define SINGLE_INPUT
#define ll long long
#define ull unsigned long long
#define N 500005
#define MOD 998244353
using namespace std;

template<class t,class u> ostream& operator<<(ostream& os,const pair<t,u>& p) {
return os<<'['<<p.first<<", "<<p.second<<']';
}
template<class t> ostream& operator<<(ostream& os,const vector<t>& v) {
os<<'['; int s = 1;
for(auto e:v) { if (s) s = 0; else os << ", "; os << e; }
return os<<']';
}
template<class t,class u> ostream& operator<<(ostream& os,const map<t,u>& mp){
os<<'{'; int s = 1;
for(auto [x,y]:mp) { if (s) s = 0; else os << ", "; os<<x<<": "<<y; }
return os<<'}';
}

vector<int> ans = {0,1,2,1,2,3,4,3,2};

int ask(int x) {
cout << "? " << x << endl;
int v;
cin >> v;
// v = ans[x];
return v;
}


void sol() {
int n;
cin >> n;
// n = 8;
int v = ask(1)-ask(1+n/2);
if (v%2) {
cout << "! -1\n";
return ;
}
int l = 1, r = n/2;
while (l<r) {
int m = l+r>>1;
int c = ask(m)-ask(m+n/2);
if (c == 0) {
cout << "! " << m << endl;
return;
} else if (v<0 && c<0 || v>0 && c>0) {
l = m+1;
} else {
r = m;
}
}
cout << "! " << n/2 << endl;
}

int main() {
cout << setprecision(15) << fixed;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifndef SINGLE_INPUT
int t;
cin >> t;
while (t--) {
sol();
}
#else
sol();
#endif
return 0;
}