题目 | Salyg1n and Array
Codeforces Round 897 (Div. 2)
E1. Salyg1n and Array (simple version)
E2. Salyg1n and Array (hard version)
https://codeforces.com/contest/1867/problem/E1
https://codeforces.com/contest/1867/problem/E2
1 second / 256 megabytes
standard input / standard output
Problem (hard version)
This is the hard version of the problem. The only difference between the versions is the limit on the number of queries. In this version, you can make no more than 57 queries. You can make hacks only if both versions of the problem are solved.
This is an interactive problem!
salyg1n has given you a positive integer
: in response to this query, you will receive . Also, after this query, the subarray will be reversed, i.e., the chosen array will become: .
You can make no more than
Input
The first line contains a single integer
Interaction
The interaction between your program and the jury's program begins with reading two positive even integers
To find the value of
You can make no more than
If your program makes more than
After printing a query do not forget to output the end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:
- fflush(stdout) or cout.flush() in C++;
- System.out.flush() in Java;
- flush(output) in Pascal;
- stdout.flush() in Python;
- see the documentation for other languages.
It is guaranteed that the sum of
To perform a hack, use the following format:
The first line contains a single integer
The description of each test case should consist of two lines. The first line contains the numbers
Example
Input
2
4 2
6
4
6 6
4
Output
? 1
? 3
! 2
? 1
! 4
Note
In the first test case, the jury has chosen the array
In the second test case, the jury has chosen the array
题解
本题的 Hard Version 实际上非常简单,因此直接略过 Easy Version.
首先,对于
for (int i = 1; i <= n - k + 1; i += k)
ans ^= query(i);
对于其他情况,长度则可以表示为
段长度为 的区间:长度共- 剩下的一段区间:长度为
对于前面
为了表示方便,对于这段长度为
下面就直接展示答案了(因为构造题确实没啥因果):
- 询问靠左的
区间,得到答案 ,代表的是 的异或和,操作后区间变成 - 询问正中心的
区间,得到答案 ,代表的是 的异或和,操作后区间变成 - 此时,
就可以得到 的异或和。此时我们发现非常巧的是, 正好跑到最左边来了。 - 询问靠右的
区间,得到答案 ,代表的是 的异或和。
综上,
(上面是一个具体的例子,如果要通式的话可以自己推导下)
总共的询问次数是
代码
#include <bits/stdc++.h>
// #define endl '\n'
// #define int long long
using namespace std;
int query(int x)
{
cout << "? " << x << endl;
int res;
cin >> res;
return res;
}
void finish(int x)
{
cout << "! " << x << endl;
return;
}
void solve()
{
int n, k;
cin >> n >> k;
int ans = 0;
// remain length: [n, 2 * n)
for (int i = 1; i + k - 1 <= n - k; i += k)
ans ^= query(i);
if (n % k)
{
int offset = (n / k - 1) * k;
int len = n - offset;
int pre = (len - k) / 2;
ans ^= query(offset + 1);
ans ^= query(offset + 1 + pre);
}
ans ^= query(n - k + 1);
finish(ans);
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi