Codeforces 835E The penguin's game

Posted yyf0309

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 109Exactly 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 ≤ 10001 ≤ x, y ≤ 109x ≠ 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 p1p2 (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 p1p2, ..., 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 p1 p2

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 1
2
1
1
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的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 F - The Sum of the k-th Powers 拉格朗日插值

CodeForces 625B War of the Corporations

CodeForces 625A Guest From the Past

CodeForces 618B Guess the Permutation

codeforces 622F. The Sum of the k-th Powers 拉格朗日插值法

CodeForces B. Obtaining the String