Codeforces Round #685 (Div. 2) E
阿新 • • 發佈:2020-11-22
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; }