CF835E The penguin's game
CF835E The penguin's game - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
设两个
为方便说明,下文所有的第
观察答案的返回值,发现返回值有四种:
- 当返回值是
时,说明有偶数个 和偶数个 ; - 当返回值是
时,说明有奇数个 和偶数个 ; - 当返回值是
时,说明有偶数个 和奇数个 ; - 当返回值是
时,说明有奇数个 和奇数个 。
显然我们更关心
如果询问反馈有偶数个
如果询问反馈有奇数个
这里我注意到,看起来后面那种反馈的信息量就更足一点。
那么本题看似选取一个子集查询的过程,其实就是将所有数分成两组的过程:查询集合里面的,和外面的。
再观察询问次数和
联想到 P5304 GXOI/GZOI2019 旅行者,有一个性质是两个数的二进制一定有某一位不同。
那道题里,我们分了
这样保证了每两个不同的数都至少一次被分在不同的组中,而且分组次数很低。
对于这个题,我们试着先询问
这样以来,一定有一次询问的反馈是落在了不同的组,我们设这是第
而且,我们顺便获取到了
我们知道,
考虑询问第
如果返回的结果是
显然查询的
如果想不到刚刚这种策略也没关系。一个更普通的想法是,直接在第
具体来讲,我们先查询【第
第
所以这部分可以
/*
* @Author: crab-in-the-northeast
* @Date: 2022-12-19 22:20:46
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2022-12-19 22:41:16
*/
#include <bits/stdc++.h>
inline int read() {
int x = 0;
bool f = true;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-')
f = false;
for (; isdigit(ch); ch = getchar())
x = (x << 1) + (x << 3) + ch - '0';
return f ? x : (~(x - 1));
}
int n, x, y;
inline int ask(int S) {
std :: vector <int> vec;
for (int i = 1; i <= n; ++i)
if ((i & S) == S)
vec.push_back(i);
if (vec.empty())
return 0;
printf("? %d ", (int)vec.size());
for (int v : vec)
printf("%d ", v);
puts("");
fflush(stdout);
int ans = read();
return (ans == y || ans == (x ^ y)) ? 1 : 0;
}
int t[15];
int main() {
n = read();
x = read();
y = read();
int k = 0;
int x = 0;
for (int i = 0; i < 10; ++i) {
t[i] = (1 << i);
int ans = ask(t[i]);
if (ans) {
k = i;
x |= t[i];
}
}
int a = t[k];
for (int i = 0; i < 10; ++i) if (i ^ k) {
if (ask(t[i] | t[k]))
a |= t[i];
}
int b = (a ^ x);
if (a > b)
a ^= b ^= a ^= b;
printf("! %d %d\n", a, b);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】