题目链接:点击进入
题目
题意
长度为n的数组(n 是 2 的幂次),数组内每个数的范围在 [ 0 , n - 1 ] ,求在最多n+1次询问下确定整个数组
询问有三种类型:
1、询问 a [ i ] and a [ j ] 的值
2、询问 a [ i ] or a [ j ] 的值
3、询问 a [ i ] xor a [ j ] 的值
思路
数组有两种情况
1、数组内出现相同值
2、数组内没有相同的值( 即 [ 0 - n - 1 ] 各自出现一次 )
首先这两种情况我们都初始先花费 n - 1 次查询,得到 a [ 1 ] 与 a [ 2 ] … a [ n ] 的 xor 值 x [ i ]
然后
对于情况 1 ,若两个值 a [ i ] 跟 a [ j ] 相同,则他们与 a [ 1 ] 的 xor 值 x [ i ] 与 x [ j ] 相同,此时询问 a [ i ] 与 a [ j ] 的 and 值,得到的就是 a[ i ] 本身,又因为 a [ 1 ] xor a [ i ] = x [ i ] ,则 a [ 1 ] = a [ i ] ^ x [ i ] ,确定了 a [ 1 ] ,有已知 a [ 1 ] 与剩余的值的 xor 值,因此确定了整个数组,共 n 次查询;同时,若两个相等的数中有一个 a [ 1 ] ,则可以通过 x [ i ] 是否等于 0 来判断
对于情况 2 ,因为 0 - n - 1 的数都有,所以必定会有 a [ i ] xor a [ j ] = n - 1 (即 a [ i ] and a [ j ] = 0 ),根据这个性质,a [ 1 ] = a [ 1 ] and a [ i ] + a [ 1 ] and a [ j ] ,通过两次询问得到 a [ 1 ] ,共 n + 1 次询问
所以最多 n + 1 次询问即可确定整个数组。
代码
//#pragma GCC optimize(3)//O3
//#pragma GCC optimize(2)//O2
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define best 131
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define lowbit(x) x & -x
#define inf 0x3f3f3f3f
//#define int long long
//#define double long double
//#define max(a,b) a>b?a:b
//#define min(a,b) a<b?a:b
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const int maxn=1e6+10;
const int mod=1e9+7;
const double eps=1e-9;
const int N=1e6+10;
int t,n,m,k,d,x[maxn],a[maxn];
map<int,int>mp;
int ask(int i,int j,int f)
{
if(f==1)
{
cout<<"AND "<<i<<" "<<j<<endl;
cout.flush();
}
else if(f==2)
{
cout<<"OR "<<i<<" "<<j<<endl;
cout.flush();
}
else if(f==3)
{
cout<<"XOR "<<i<<" "<<j<<endl;
cout.flush();
}
int x;
cin>>x;
return x;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=2;i<=n;i++)
x[i]=ask(1,i,3);
int flag=-1;
for(int i=2;i<=n;i++)
{
if(x[i]==0)
{
flag=ask(1,i,1);
break;
}
if(mp.count(x[i]))
{
int tmp=mp[x[i]];
flag=ask(tmp,i,1);
flag=flag^x[i];
break;
}
mp[x[i]]=i;
}
if(flag==-1)
{
mp.clear();
for(int i=2;i<=n;i++)
{
if(mp.count((n-1)^x[i]))
{
int num1=mp[(n-1)^x[i]];
int num2=i;flag=0;
flag+=ask(1,num1,1);
flag+=ask(1,num2,1);
break;
}
mp[x[i]] = i;
}
}
a[1]=flag;
for(int i=2;i<=n;i++)
a[i]=a[1]^x[i];
cout<<"!";
cout.flush();
for(int i=1;i<=n;i++)
cout<<" "<<a[i],cout.flush();
cout<<endl;
return 0;
}