P8849 『JROI-7』hibernal 做题笔记
观察数据,要求询问次数不超过
我刚开始也在想二分,但这个东西并不具有单调性,但这个题具有的特点就是你不仅仅可以询问一个前缀,你还可以询问任意的集合。
首先发现如果能将
怎么解决呢?我们假设去分
随便取一个
但是我们暂时没有想到合适的方法能够用
所以我想到了在求
这里需要用到二进制分组的技巧啦!
从高到低地考虑每一个二进制位,将所有的位置按照这一位二进制位分为两个部分:一是这一位是
我们来看看能够得到些什么,如果返回
如果是
这样一定能得到一组询问答案是
这样就花去了
那另一个呢?我们不是求出金苹果两个每一个二进制位是否相同了吗?所以也解决了。其实熟练的人看一下就知道了那个是异或值,所以假如知道了
超短代码:
#include <iostream> #define For(i, a, b, j) for (int i = (a); i <= (b); i = (j) ) using namespace std; int T, n, k, kx; int x, oplus; int a[505], b[505]; int find (int l, int r) { if (l == r) return b[l]; int mid = l + r >> 1; printf ("? %d ", mid - l + 1); For (i, l, mid, i + 1) printf ("%d ", b[i]); printf ("\n"); fflush (stdout); scanf ("%d", &x); if (x == 1) return find (l, mid); return find (mid + 1, r); } int main () { fflush (stdout); scanf ("%d", &T); while (T --) { oplus = 0; fflush (stdout); scanf ("%d", &n); For (m, 1, n, m << 1) { k = 0; For (i, 1, n, i + 1) if ( (i & m) == 0) a[++ k] = i; printf ("? %d ", k); For (i, 1, k, i + 1) printf ("%d ", a[i]); printf ("\n"); fflush (stdout); scanf ("%d", &x); oplus += x * m; if (x == 1) { For (i, 1, k, i + 1) b[i] = a[i]; kx = k; } } int ans = find (1, kx); printf ("! %d %d\n", min (ans, ans ^ oplus), max (ans, ans ^ oplus) ); fflush (stdout); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异