Codeforces Round #685 (Div. 2) E
Codeforces Round #685 (Div. 2) E
大意
略...
思路
交互题,莫名好玩...
首先,我们需要确定一个位置作为基准,没什么特殊条件,于是假定选择第一位作为基准,记为 \(a_1\)
因为题目保证了数字范围,所以仅有两种情况:
- 有相同的数
- 一个排列
先考虑一:
如果有两个相同的数,那么他们和 \(a_1\) 的异或值一定一样,于是我们对值一样的位置查询一下 与 ,我们就得到了数列中的两个值。
此时我们耗费了至多 \(n\) 次查询。
那么我们知道了一个值,知道了这个值和 \(a_1\) 的异或值,又知道了 \(a_1\) 和其余数的异或值,可以很轻松的推出来原数组了。
所以情况一至多耗费 \(n\) 次查询。
情况二:
当我们在 \(n-1\) 次查询后发现没有相同的值,那么,原数组肯定是一个排列。
考虑如何获得 \(a_1\) 的值。
因为是排列,肯定存在两个数的与 \(a_1\) 的异或值分别为 \(2,1\) ,分别记为 \(a_i,a_j\)
显然,\(a_i\) 与 \(a_1\) 二进制除了第二位都相同, \(a_j\) 与 \(a_1\) 二进制除了第一位都相同。
所以我们查询 \(a_1,a_i\) 的 与 操作的值,就可以知道 \(a_1\) 在二进制下第一位的值。
再查询 \(a_1,a_j\) 的 与 操作的值,然后就能推出 \(a_1\)
于是就可以退出原数组了
所以情况二严格耗费 \(n+1\) 次查询
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)
const int mod = 998244353;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;
int n;
int sum[(1<<16)+1];
int ans[(1<<16)+1];
int query(cint key, cint x, cint y) {
int tmp;
if(key==1) cout << "AND " << x << ' ' << y << endl;
else if(key==2) cout << "OR " << x << ' ' << y << endl;
else if(key==3) cout << "XOR " << x << ' ' << y << endl;
cout.flush();
cin >> tmp;
return tmp;
}
int main() {
cin >> n;
int a, id=0, lf=0;
sum[0]=1;
for(int i=2; i<=n; i++) {
a = query(3, 1, i);
ans[i] = a;
if(!sum[a]) sum[a] = i;
else id=i;
}
if(id) {
int key = query(1, sum[ans[id]], id);
ans[1] = ans[id] ^ key;
for(int i=2; i<=n; i++)
ans[i] ^= ans[1];
} else {
bool flag=0;
int k1 = sum[1];
int k2 = sum[2];
int a1 = query(1, k1, 1);
int a2 = query(1, k2, 1);
int key = a1 + a2%2;
for(int i=1; i<=n; i++) ans[i] ^= key;
}
cout << "! ";
for(int i=1; i<=n; i++) cout << ans[i] << ' ';
return 0;
}