Codeforces 835E The penguin's game

Pay attention: this problem is interactive.

Penguin Xoriy came up with a new game recently. He has n icicles numbered from 1 to n. Each icicle has a temperature — an integer from 1 to 109. Exactly two of these icicles are special: their temperature is y, while a temperature of all the others is x ≠ y. You have to find those special icicles. You can choose a non-empty subset of icicles and ask the penguin what is the bitwise exclusive OR (XOR) of the temperatures of the icicles in this subset. Note that you can‘t ask more than 19 questions.

You are to find the special icicles.

Input

The first line contains three integers nxy (2 ≤ n ≤ 1000, 1 ≤ x, y ≤ 109, x ≠ y) — the number of icicles, the temperature of non-special icicles and the temperature of the special icicles.

Output

To give your answer to the penguin you have to print character "!" (without quotes), then print two integers p1, p2 (p1 < p2) — the indexes of the special icicles in ascending order. Note that "!" and p1 should be separated by a space; the indexes should be separated by a space too. After you gave the answer your program should terminate immediately.

Interaction

To ask a question print character "?" (without quotes), an integer c (1 ≤ c ≤ n), and c distinct integers p1, p2, ..., pc (1 ≤ pi ≤ n) — the indexes of icicles that you want to know about. Note that "?" and c should be separated by a space; the indexes should be separated by a space too.

After you asked the question, read a single integer — the answer.

Note that you can‘t ask more than 19 questions. If you ask more than 19 questions or at least one incorrect question, your solution will get "Wrong answer".

If at some moment your program reads  - 1 as an answer, it should immediately exit (for example, by calling exit(0)). You will get "Wrong answer" in this case, it means that you asked more than 19 questions, or asked an invalid question. If you ignore this, you can get other verdicts since your program will continue to read from a closed stream.

Your solution will get "Idleness Limit Exceeded", if you don‘t print anything or forget to flush the output, including for the final answer .

To flush you can use (just after printing):

  • fflush(stdout) in C++;
  • System.out.flush() in Java;
  • stdout.flush() in Python;
  • flush(output) in Pascal;
  • For other languages see the documentation.

Hacking

For hacking use the following format:

n x y pp2

Here 1 ≤ p1 < p2 ≤ n are the indexes of the special icicles.

Contestant programs will not be able to see this input.

Example

input

4 2 1211

output

? 3 1 2 3? 1 1? 1 3! 1 3

Note

The answer for the first question is .

The answer for the second and the third questions is 1, therefore, special icicles are indexes 1 and 3.

You can read more about bitwise XOR operation here: https://en.wikipedia.org/wiki/Bitwise_operation#XOR.


题目大意 有一个长度为$n$的数组,其中包含$\left(n - 2\right)$正整数$x$,和2个正整数是$y$。每次可以询问一些位置上的数的异或和,至多可以询问19次,要求最后输出2个$y$的下标。

  来考虑一下,如果只有1个$y$,那么应该怎么做?

  二分区间$[l, r]$对吧,取中点$mid$,然后询问$[l, mid]$的异或和,如果结果为$x$ ^ $y$或者$y$,那么说明这个$y$在左区间,就把$r$设为$mid$。否则就把$l$设为$mid + 1$。

  然后考虑是否能把这个做法推广到2个$y$的时候。

  然后开心地发现,如果两个$y$在同侧就非常尴尬,因为并不知道是同在哪边。

  于是考虑如何强行把两个$y$分开。

  考虑到两个$y$的下标不相同。所以,它们的二进制表示至少存在1位不同。因此我可以考虑每一位,然后询问所有下标的二进制此位为1的位置上的数的异或和,判断它们是否为$y$或者$x$ ^ $y$。

  这样就可以将原数组分成两个集合。使得每个集合中恰好有1个$y$,于是便可以在上面二分。

  于是来计算一下最坏的询问次数:$10 + 9 \times 2 = 28 > 19$。好像超了。。怎么办?

  发现$10 + 9$恰好等于$19$,那么考虑如何去掉1个9。有注意到,开始你已经确定了两个$y$的下标的每一个二进制位是否相同,所以只用求1个,就知道另外一个了。

Code

 1 /**
 2  * Codeforces
 3  * Problem#835E
 4  * Accepted
 5  * Time: 15ms
 6  * Memory: 2028k
 7  */
 8 #include <bits/stdc++.h>
 9 using namespace std;
10 typedef bool boolean;
11
12 int n, x, y;
13
14 inline void init() {
15     scanf("%d%d%d", &n, &x, &y);
16 }
17
18 int ask(vector<int> &v) {
19     printf("? %d", (signed)v.size());
20     for(int i = 0; i < (signed)v.size(); i++)
21         printf(" %d", v[i]);
22     printf("\n");
23     int rt;
24     fflush(stdout);
25     scanf("%d", &rt);
26     return rt;
27 }
28
29 int ueq;
30 boolean beq[15];
31 int posa, posb;
32
33 boolean check(vector<int>& v, int l, int mid) {
34     vector<int> g;
35     for(int i = l; i <= mid; i++)
36         g.push_back(v[i]);
37     int ans = ask(g);
38     return ans == (x ^ y) || ans == y;
39 }
40
41 inline void solve() {
42     memset(beq, true, sizeof(beq));
43     for(int s = 0, ans; (1 << s) <= n; s++) {
44         vector<int> v;
45         for(int i = 1; i <= n; i++)
46             if(i & (1 << s))
47                 v.push_back(i);
48         ans = ask(v);
49         if(ans == y || ans == (x ^ y)) {
50             beq[s] = false, ueq = s;
51         }
52     }
53
54     vector<int> v;
55     for(int i = 1; i <= n; i++)
56         if(i & (1 << ueq))
57             v.push_back(i);
58
59     int l = 0, r = v.size() - 1;
60     while(l < r) {
61         int mid = (l + r) >> 1;
62         if(check(v, l, mid))    r = mid;
63         else    l = mid + 1;
64     }
65
66     posa = posb = v[r];
67     for(int i = 0; (1 << i) <= n; i++)
68         if(!beq[i])
69             posb ^= (1 << i);
70     if(posa > posb)    swap(posa, posb);
71     printf("! %d %d", posa, posb);
72     fflush(stdout);
73 }
74
75 int main() {
76     init();
77     solve();
78     return 0;
79 }

Codeforces 835E The penguin's game

原文地址:https://www.cnblogs.com/yyf0309/p/8277904.html

时间: 2024-10-09 01:31:19

Codeforces 835E The penguin's game的相关文章

Codeforces.835E.The penguin&#39;s game(交互 按位统计 二分)

题目链接 \(Description\) 有一个长为\(n\)的序列,其中有两个元素为\(y\),其余全为\(x\).你可以进行\(19\)次询问,每次询问你给出一个下标集合,交互库会返回这些元素的异或和.给定\(n,x,y\),你需要求出两个\(y\)的下标. \(n\leq 1000,1\leq x,y\leq 10^9\). \(Solution\) 对连续区间询问得到的结果只有那么几种,可以直接判断\(y\)的个数的奇偶性.但是区分不出来该区间有0个还是2个\(y\). 两个\(y\)的

codeforces 289B - Polo the Penguin and Matrix 二分+dp

题意:给你一个序列,每一次可以对序列里面任意数+d 或者 -d 问你最少多少步能够使得数列里面所有的数相等 解题思路:从 1 - 10000 枚举这个数,二分找数列中小于等于它的最大的那个数,然后求前缀和以后刻意快速求出差值和的绝对值,差值和/d 就是我们所求数. 解题代码: 1 // File Name: 289b.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月29日 星期二 22时33分11秒 4 5 #include<vecto

Codeforces Round #177 (Div. 1) C. Polo the Penguin and XOR operation(贪心)

题目地址:http://codeforces.com/problemset/problem/288/C 思路:保证位数尽量大的情况下使得每二进制位均为一的情况下结果最大,从后向前枚举(保证位数尽量大),num表示该数i二进制有几位,x即为使得与i异或后每二进制位均为一的数,v[x]标记是否使用过该数,若未使用则与i搭配. #include<cstdio> #include<cmath> #include<cstring> #include<iostream>

Codeforces Round #177 (Div. 2)---D. Polo the Penguin and Houses (组合数学+暴力)

Little penguin Polo loves his home village. The village has n houses, indexed by integers from 1 to n. Each house has a plaque containing an integer, the i-th house has a plaque containing integer pi (1?≤?pi?≤?n). Little penguin Polo loves walking ar

codeforces 288A:Polo the Penguin and Strings

Description Little penguin Polo adores strings. But most of all he adores strings of length n. One day he wanted to find a string that meets the following conditions: The string consists of n lowercase English letters (that is, the string's length eq

Codeforces Round #177 (Div. 2)---E. Polo the Penguin and XOR operation(贪心)

Little penguin Polo likes permutations. But most of all he likes permutations of integers from 0 to n, inclusive. For permutation p?=?p0,?p1,?-,?pn, Polo has defined its beauty - number . Expression means applying the operation of bitwise excluding "

Codeforces Round #177 (Div. 2)---E. Polo the Penguin and XOR operation

题意:让你构造一个序列,使得序列异或和最大,序列为n 的全排列 ,序列和计算方式为 SUM = a[1] ^ 0 + a[2] ^ 1 + a[3] ^ 2 + .......a[n] ^ n 感想 :之前没做过有关位运算的题,对这一块很陌生,两个数异或以后,如果二进制每一位都为1,那么一定最大,找规律发现当n为偶数时 除开0以外,其他的都是成对出现 当n为奇数时 都是成对出现 例如n=4, 0 1 2 3 4 分别对应0 2 1 4 3 :n=5时 0 1 2 3 4 5 分别对应1 0 5

CodeForces 288C - Polo the Penguin and XOR operation(思维)

题意: 就是让你构造一个序列,使得序列异或和最大,序列为n 的全排列 ,序列和计算方式为   SUM  =   a[1] ^ 0 + a[2] ^ 1 + a[3] ^ 2 + .......a[n] ^ n 构造出一个序列使得和最大 题解: 策略为使得每次异或出来的结果的1尽可能多,而优先从最大的n  开始考虑,因为n  最有可能出更大的数字 代码: #include<stdio.h> #include<string.h> int Ans[1000005]; int main()

CodeForces 288C - Polo the Penguin and XOR operation(思路)

题意:给定一个 n (1 <= n <= 10^6),求(0 ^ p0) + (1 ^ p1) + (2 ^ p2) +-- + (n ^ pn) 的最大值,其中p0 ~ pn为 0 ~ n 中的数,且每个数只利用一次. 从n ~ 0枚举所有的数,对于每个数找它异或后得到二进制都是 1 的数或者 1 尽量多的数. 对于每个数,先找到与它二进制位数相同的全是 1 的数,然后把这个当成结果,与目前的数异或得到另一个数并记录,然后同时记录另一个数(可能用不到,但是为了节省时间). 加起来的结果可能超