CF1451E2 Bitwise Queries (Hard Version)
题意:
有 \(n\) 个数( \(n\le 2^{16}\) ,且为 \(2\) 的整数次幂,且每一个数都属于区间 \([0,n-1]\) ) 可以通过询问交互库不超过 \(n+1\) 次询问,每次询问编号为 \(i,j\) ( \(1\le i,j \le n\) ,\(i\ne j\) ) 的 XOR
、OR
或 AND
,求出这 \(n\) 个数 。
题解:
分类讨论,先对 \(2-n\) 这 \(n-1\) 个数每个数都与 \(1\) 询问一次 XOR
,之后考虑 \(2\) 次求出 \(a_1\) 。
-
所有数都互不相同
此时所有 \(xor\) 值都不相同且都不等于 \(0\) ,可以分别找出 \(xor_i=1\) 与 \(xor_j=n-2\) 的数,用 \(1\) 一次 \(and\) 询问求出 \(a_1\) 的前 \(m\) 位与最后一位 。
-
有些数相同
那些数的 \(xor\) 值相同 。
-
有些数与 \(a_1\) 相同
找出 \(xor_i=0\) 的数,与 \(1\) 询问
AND
,直接求出 \(a_1\) 。 -
有些数相同,但不等于 \(a_1\)
找出两个 \(xor\) 相同的数,用 \(1\) 次询问求出 \(a_i\) ,进而用之前询问求得的 \(xor_i\) 求出 \(a_1\) 。
-
代码:
#include<bits/stdc++.h>
using namespace std;
#define Maxn 65540
inline int rd()
{int x=0;char ch,t=0;while(!isdigit(ch = getchar())) t|=ch=='-';while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();return x=t?-x:x;
}
int n,Xor[Maxn],ans[Maxn],vis[Maxn];
bool All=true;
inline int XOR(int x,int y)
{printf("XOR %d %d\n",x,y),fflush(stdout);return rd();
}
inline int AND(int x,int y)
{printf("AND %d %d\n",x,y),fflush(stdout);return rd();
}
int main()
{//freopen(".in","r",stdin);//freopen(".out","w",stdout);n=rd();for(int i=2;i<=n;i++){Xor[i]=XOR(1,i);if(vis[Xor[i]] || Xor[i]==0) All=0;vis[Xor[i]]=1;}if(All){for(int i=2;i<=n;i++){if(Xor[i]==1) ans[1]|=AND(1,i);if(Xor[i]==n-2) ans[1]|=AND(1,i);}}else{if(vis[0]){for(int i=2;i<=n;i++) if(!Xor[i]) { ans[1]=AND(1,i); break; }}else{for(int i=0;i<=n-1;i++) vis[i]=0;for(int i=2;i<=n;i++){if(vis[Xor[i]]) { ans[1]=Xor[i]^AND(vis[Xor[i]],i); break; }vis[Xor[i]]=i;}}}for(int i=2;i<=n;i++) ans[i]=ans[1]^Xor[i];printf("! ");for(int i=1;i<=n;i++) printf("%d%c",ans[i],(i==n)?'\n':' ');fflush(stdout);//fclose(stdin);//fclose(stdout);return 0;
}