E1. Bitwise Queries (Easy Version)
a
+
b
=
(
a
&
b
)
+
(
a
∣
b
)
a+b=(a\&b)+(a|b)
a+b=(a&b)+(a∣b)
根据上述式子用
3
3
3次$&和
3
3
3次
∣
|
∣操作求出
a
1
+
a
2
,
a
2
+
a
3
,
a
1
+
a
3
a_1+a_2,a_2+a_3,a_1+a_3
a1+a2,a2+a3,a1+a3由此得出
a
1
,
a
2
,
a
3
a_1,a_2,a_3
a1,a2,a3
根据
a
1
⊕
a
i
=
x
a_1\oplus a_i=x
a1⊕ai=x于是
a
i
=
x
⊕
a
1
a_i=x\oplus a_1
ai=x⊕a1可使用
n
−
3
n-3
n−3次
⊕
\oplus
⊕操作得出答案
共计
n
+
3
n+3
n+3次。。。
大佬题解
a
+
b
=
(
a
⊕
b
)
+
2
×
(
a
&
b
)
a+b=(a\oplus b)+2×(a\&b)
a+b=(a⊕b)+2×(a&b)
如果已知
a
1
⊕
a
2
,
a
2
⊕
a
3
a_1\oplus a_2,a_2 \oplus a_3
a1⊕a2,a2⊕a3那么
a
1
⊕
a
3
=
(
a
1
⊕
a
2
)
⊕
(
a
2
⊕
a
3
)
a_1\oplus a_3=(a_1\oplus a_2)\oplus (a_2\oplus a_3)
a1⊕a3=(a1⊕a2)⊕(a2⊕a3)
那么只需用
5
5
5次就可以知道
a
1
,
a
2
,
a
3
a_1,a_2,a_3
a1,a2,a3最终用
n
+
2
n+2
n+2次得出答案。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=998244353;
const int N=100010;
int x,y,z;
void prework()
{
int ab1,ab2,ac1,ac2,bc1,bc2;
printf("XOR 1 2\n");
fflush(stdout);
cin>>ab1;
printf("AND 1 2\n");
fflush(stdout);
cin>>ab2;
printf("XOR 1 3\n");
fflush(stdout);
cin>>ac1;
printf("AND 1 3\n");
fflush(stdout);
cin>>ac2;
bc1 = ab1 ^ ac1;
printf("AND 2 3\n");
fflush(stdout);
cin>>bc2;
x=ab1+2*ab2;
y=ac1+2*ac2;
z=bc1+2*bc2;
}
int main()
{
IO;
int T=1;
//cin>>T;
while(T--)
{
int n;
cin>>n;
vector<int> ans(n+1);
prework();
ans[1]=(x+y-z)/2;
ans[2]=(x+z-y)/2;
ans[3]=(y+z-x)/2;
for(int i=4;i<=n;i++)
{
int tmp;
printf("XOR 1 %d\n",i);
fflush(stdout);
cin>>tmp;
ans[i]=tmp^ans[1];
}
cout<<"! ";
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
cout<<'\n';
}
return 0;
}
E2. Bitwise Queries (Hard Version)
大佬题解
同样只要我们能确认一个值,其余的值都能通过异或来得到。由此我们目标是确定一个值。
注意到 0 < x i < n − 1 0<x_i<n-1 0<xi<n−1,由此数组有两种情况
- 数组元素不重复,各不相同
- 数组元素重复
①对于数组元素重复的情况,我们首先进行
n
−
1
n-1
n−1次
x
1
⊕
x
i
x_1\oplus x_i
x1⊕xi将异或值记入数组
a
i
a_i
ai,不难发现其中肯定存在相同的值,只要记录相同值的位置
i
,
j
i,j
i,j那么只需要进行一次
x
i
&
x
j
x_i\&x_j
xi&xj即可知道
x
i
x_i
xi和
x
j
x_j
xj,那么就能根据
a
i
a_i
ai或者
a
j
a_j
aj得出
x
1
x_1
x1进而得出答案。操作
n
n
n次
②如果不存在那么一定有某个数与第一个数相差1,
a
i
=
1
a_i=1
ai=1,即
x
i
⊕
x
1
=
1
x_i\oplus x_1=1
xi⊕x1=1,于是 不难得知
x
1
x_1
x1和
x
i
x_i
xi分别是
(
x
1
&
x
i
)
(x_1\& x_i)
(x1&xi)和
(
x
1
&
x
i
)
⊕
1
(x_1\& x_i)\oplus1
(x1&xi)⊕1
然后随便找一个与第一个数奇偶性相同的数(
a
i
&
1
=
0
a_i\&1=0
ai&1=0)用一次
&
\&
&操作
x
1
&
x
i
x_1\&x_i
x1&xi的奇偶性即是
x
1
x_1
x1的奇偶性,于是可以得出
x
1
x_1
x1。操作
n
+
1
n+1
n+1次
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=998244353;
const int N=200010;
int a[N];
map<int,int> pos;
int main()
{
//IO;
int T=1;
//cin>>T;
while(T--)
{
int n;
cin>>n;
pos.clear();
pos[0]=1;
int k=0,v;
for(int i=2;i<=n;i++)
{
printf("XOR 1 %d\n",i);
fflush(stdout);
cin>>a[i];
if(pos[a[i]]&&!k)
{
printf("AND %d %d\n",pos[a[i]],i);
fflush(stdout);
cin>>v;
k=i;
}
pos[a[i]]=i;
}
if(k) a[1]=a[k]^v;
else
{
printf("AND 1 %d\n",pos[1]);
fflush(stdout);
cin>>a[1];
for(auto t:pos)
{
if((t.first&1)||t.second==1) continue;
printf("AND 1 %d\n",t.second);
fflush(stdout);
int c; cin>>c;
if(c&1) a[1]^=1;
break;
}
}
cout<<"! "<<a[1]<<' ';
for(int i=2;i<=n;i++)
cout<<(a[i]^a[1])<<' ';
cout<<'\n';
}
return 0;
}
要加油哦~