Codeforces Round #427 (Div. 2) E. The penguin's game(交互+思维+二分)

来源:互联网 发布:阿里云已备案域名 编辑:程序博客网 时间:2024/05/29 09:50

题目链接

原版题解:

The solution can be separated into several parts.

I. Finding the parity of the number of special icicles in the given subset using 1 question.

Consider the following cases:

  1. Subset's size is even, the number of special icicles in it is even. Then the answer to such question is 0.
  2. Subset's size is even, the number of special icicles in it is odd. Then the answer to such question is .
  3. Subset's size is odd, the number of special icicles in it is even. Then the answer to such question is x.
  4. Subset's size is odd, the number of special icicles in it is odd. Then the answer to such question is y.

x, y ≥ 1 and x ≠ y, so the numbers 0xy are pairwise distinct. Therefore, we can find the parity of the number of special icicles on the given subset using 1 question.

II. The solution for the problem for the only one special icicle.

Suppose we have n icicles, and one of them is special. Then you can find it using  questions.

The algorithm is to use binary search over the minimum prefix that contains the special icicle.

III. The solution of our problem.

Each integer n ≤ 1000 can be written using no more than  bits. Iterate over the bits from 0 to . Ask a question about the icicles that have 1 in their numbers in the fixed bit. After that, we can determine if the numbers of the special icicles differ in this bit. Really, the bits differ if this subset's size is odd, and don't differ otherwise.

Obviously, we will find at least one bit, where their numbers differ. Let A is the subset of the icicles that have 1 in this bit, and B is the complement set. Let m is the size of the smallest from these subsets. Then . Let's solve the problem for the only one special icicle for the smallest of these subsets.

Then it's easy to get the number of the other icicle: we know the number of the first icicle and we know in which bits the numbers differ and in which don't.

This solution uses 19 question. It can be proven that in the given constraints you can't solve this problem in less than 19 questions

下面是对于题解的补充:上面的题解就是说设两个y元素的位置分别为pos1,pos2,我们可以先用O(logn)次询问找到pos1和pos2转化为二进制后有哪些不同的位(通过枚举每个位为1时的所有情况进行询问,用上面1中的结论,从中挑出y的个数为1的情况进行记录),设为diff,其中一个不同位为diff_bit。那么我们可以把那些第diff_bit位为1的位置拿出来,设为集合a,集合b为集合a的补集,那么a和b一定有一个是不大于n/2的,且必然pos1和pos2分别位于不同的集合。 
那么我们只要对小的那个集合进行二分查找,找到pos1后,那么pos2=pos1^diff。

具体实现见代码:

#include <bits/stdc++.h>using namespace std;int pow2[11];vector<int> a,b,c;int n,x,y,p;int dif;int ask(vector<int> a){if(a.empty()) return 0;printf("? %d ",a.size());for(int i = 0;i < a.size();i++) printf("%d ",a[i]);printf("\n");int tmp;cin >> tmp;return tmp;}int getans(vector<int> b){int left = 0,right = b.size() - 1;vector<int> a;while(left < right){int mid = (left + right) / 2;a.clear();for(int i = left;i <= mid;i++){a.push_back(b[i]);}int tmp = ask(a);if(tmp == (x ^ y) || tmp == y) right = mid;else left = mid + 1;}return b[left];}int main(){scanf("%d%d%d",&n,&x,&y);pow2[0] = 1;for(int i = 1;i <= 10;i++) pow2[i] = 2 * pow2[i - 1];for(int i = 0;i <= 9;i++){a.clear();for(int j = 1;j <= n;j++){if(j & pow2[i]) a.push_back(j);}int tmp = ask(a);if(tmp == y || tmp == (x ^ y)) {dif |= pow2[i];p = i;}}int q = pow2[p];for(int i = 1;i <= n;i++){if(i & q) b.push_back(i);else c.push_back(i);}int ans1 = 0,ans2 = 0;if(b.size() < c.size()) ans1 = getans(b);else ans1 = getans(c);ans2 = (ans1 ^ dif);if(ans1 > ans2) swap(ans1,ans2);printf("! %d %d\n",ans1,ans2);return 0;}


阅读全文
0 0