E1. Bitwise Queries (Easy Version)
a+b=(a&b)+(a∣b)a+b=(a\&b)+(a|b)a+b=(a&b)+(a∣b)
根据上述式子用333次$&和333次∣|∣操作求出a1+a2,a2+a3,a1+a3a_1+a_2,a_2+a_3,a_1+a_3a1+a2,a2+a3,a1+a3由此得出a1,a2,a3a_1,a_2,a_3a1,a2,a3
根据a1⊕ai=xa_1\oplus a_i=xa1⊕ai=x于是ai=x⊕a1a_i=x\oplus a_1ai=x⊕a1可使用n−3n-3n−3次⊕\oplus⊕操作得出答案
共计n+3n+3n+3次。。。
大佬题解
a+b=(a⊕b)+2×(a&b)a+b=(a\oplus b)+2×(a\&b)a+b=(a⊕b)+2×(a&b)
如果已知a1⊕a2,a2⊕a3a_1\oplus a_2,a_2 \oplus a_3a1⊕a2,a2⊕a3那么a1⊕a3=(a1⊕a2)⊕(a2⊕a3)a_1\oplus a_3=(a_1\oplus a_2)\oplus (a_2\oplus a_3)a1⊕a3=(a1⊕a2)⊕(a2⊕a3)
那么只需用555次就可以知道a1,a2,a3a_1,a_2,a_3a1,a2,a3最终用n+2n+2n+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<xi<n−10<x_i<n-10<xi<n−1,由此数组有两种情况
- 数组元素不重复,各不相同
- 数组元素重复
①对于数组元素重复的情况,我们首先进行n−1n-1n−1次x1⊕xix_1\oplus x_ix1⊕xi将异或值记入数组aia_iai,不难发现其中肯定存在相同的值,只要记录相同值的位置i,ji,ji,j那么只需要进行一次xi&xjx_i\&x_jxi&xj即可知道xix_ixi和xjx_jxj,那么就能根据aia_iai或者aja_jaj得出x1x_1x1进而得出答案。操作nnn次
②如果不存在那么一定有某个数与第一个数相差1,ai=1a_i=1ai=1,即xi⊕x1=1x_i\oplus x_1=1xi⊕x1=1,于是 不难得知x1x_1x1和xix_ixi分别是(x1&xi)(x_1\& x_i)(x1&xi)和(x1&xi)⊕1(x_1\& x_i)\oplus1(x1&xi)⊕1
然后随便找一个与第一个数奇偶性相同的数(ai&1=0a_i\&1=0ai&1=0)用一次&\&&操作x1&xix_1\&x_ix1&xi的奇偶性即是x1x_1x1的奇偶性,于是可以得出x1x_1x1。操作n+1n+1n+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;
}
要加油哦~