1. 程式人生 > >Codeforces 835E The penguin's game

Codeforces 835E The penguin's game

quest rate 2個 lin c++ nat first ng- verdi

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 n, x, y (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 p

1, 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 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