XorForces。每日被 Hack。
首先考虑异或的性质:
壹 若 ,则 。
壹.证明 若 ,则 和 二进制表示下每一位的值都相同,显然只有两个数完全相同时才能有这样的性质。因此得证。
贰 若 ,则 。
贰.证明 若 ,则令 且 的第 位的值不为 。此时 的第 位的值和 的第 位的值不同。因此 和 的值不能相等。因此得证。
叁 若 且 互不相同,则钦定 ,设 表示 二进制表示下最高的为 位是第几位。则必有 。
叁.证明
首先 函数在 上单调不递减。证明显然。
若 ,则 位上必然只有一个 ,异或完后这一位的值还是 ,无法清零。若 则 位上必然有 个 ,无法清零。因此当且仅当 时 位有 个 可以清零,有可能满足 的条件。
考虑开始做这个题。令三个只有一次出现的数的值分别为 并满足 。则:
- 即 。则此时在给定集合 中任选子集 且 ,均满足 ()。因此直接在值域上先后以前缀 / 后缀二分答案,可以在 次询问内得出结果。然后询问 这个值域区间,即可以得到 的值。
- 即 。则此时上面的贪心二分做法显然可以被 hack 掉。根据上面的结论叁可以得知若 且 则 。因此考虑 次询问按位枚举得到 的最高位。此时该前缀值域内有且仅有 一个元素。然后一次询问得到 的值。剩下的后缀值域区间内有 , 两个不相同的元素且满足 。因此直接在后缀值域的前缀上贪心二分 次询问找出 的值,随后对剩余的后缀值域一次询问得出 的值即可。
总询问次数为 级别,附带常数不超过 ,总询问次数最多为 次,可以通过问题。
代码:
namespace ttq012 {
int op(int x) {
if (x % 4 == 0) {
return x;
} else if (x % 4 == 1) {
return 1;
} else if (x % 4 == 2) {
return x + 1;
} else {
return 0;
}
}
int calc(int l, int r) {
return op(l - 1) ^ op(r);
}
mt19937_64 mt(time(0));
int n;
void run() {
int T = read();
while (T--) {
n = read();
cout << "xor 1 " << n << endl;
int o ; cin >> o;
vector<int> result;
if (o != 0) {
int l = 1, r = n, best = -1;
while (l <= r) {
int mid = l + r >> 1;
cout << "xor 1 " << mid << endl;
int o ; cin >> o;
if (!o) {
l = mid + 1;
} else {
r = mid - 1, best = mid;
}
}
assert(~best);
result.eb(best);
l = 1, r = n, best = -1;
while (l <= r) {
int mid = l + r >> 1;
cout << "xor " << mid << ' ' << n << endl;
int o ; cin >> o;
if (!o) {
r = mid - 1;
} else {
l = mid + 1, best = mid;
}
}
assert(~best);
result.eb(best);
cout << "xor " << result[0] + 1 << ' ' << result[1] - 1 << endl;
int o ; cin >> o;
result.eb(o);
} else {
int now = 0;
for (int i = 60; ~i; --i) {
if (now + (1ll << i) - 1 <= n) {
cout << "xor 1 " << now + (1ll << i) - 1 << endl;
int o ; cin >> o;
if (o) {
now = 1ll << i;
break;
}
}
}
--now;
cout << "xor " << 1 << ' ' << now << endl;
cin >> now;
result.eb(now);
int l = now + 1, r = n, best = -1;
while (l <= r) {
int mid = l + r >> 1;
cout << "xor " << now + 1 << ' ' << mid << endl;
int o ; cin >> o;
if (!o) {
l = mid + 1;
} else {
r = mid - 1, best = mid;
}
}
result.eb(best);
cout << "xor " << result[1] + 1 << ' ' << n << endl;
int o ; cin >> o;
result.eb(o);
}
cout << "ans ";
sort(result.begin(), result.end());
for (auto &x : result) {
cout << x << ' ';
}
cout << endl;
}
}
}
signed main() {
ttq012::run();
return 0;
}
/*
*/
喜欢的话,留下你的评论吧~