1451E2 - Bitwise Queries (Hard Version)(交互,思维,位运算猜数组)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1451E2 - Bitwise Queries (Hard Version)(交互,思维,位运算猜数组)相关的知识,希望对你有一定的参考价值。
先用 n − 1 n-1 n−1次操作得到所有 a i ⊕ a i − 1 a_i\\oplus a_{i-1} ai⊕ai−1
还剩 3 3 3步可以知晓任意一个数,根据异或的性质就能求出其他所有数
考虑到用两次操作可以得到两数之和
a + b = 2 ∗ ( a & b ) + ( a ⊕ b ) a+b=2*(a\\&b)+(a\\oplus b) a+b=2∗(a&b)+(a⊕b)
考虑能否得到三数之和,我们考虑先求出三数之和的两倍
2 ∗ ( a + b + c ) = ( a + b ) + ( a + c ) + ( b + c ) 2*(a+b+c)=(a+b)+(a+c)+(b+c) 2∗(a+b+c)=(a+b)+(a+c)+(b+c)
显然可以用六次操作得到这个,于是就知道了 a , b , c a,b,c a,b,c分别是什么
然且当 a , b , c a,b,c a,b,c分别取 a 1 , a 2 , a 3 a_1,a_2,a_3 a1,a2,a3,异或值是已经知晓的,只需要询问与
这样一来,刚好操作次数是 ( n − 1 ) + 3 = n + 2 (n-1)+3=n+2 (n−1)+3=n+2
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
int n,e[maxn],a[maxn];
int OR(int l,int r)
{
cout << "OR " << l << " " << r << endl;
int x; cin >> x;
return x;
}
int XOR(int l,int r)
{
cout << "XOR " << l << " " << r << endl;
int x; cin >> x;
return x;
}
int AND(int l,int r)
{
cout << "AND " << l << " " << r << endl;
int x; cin >> x;
return x;
}
int main()
{
cin >> n;
for(int i=2;i<=n;i++) e[i] = XOR(i-1,i);
int xor_ab = e[2], xor_bc = e[3], xor_ac = e[2]^e[3];
int and_ab = AND(1,2), and_bc = AND( 2,3 ), and_ac = AND( 1,3 );
int abc = ( 2*( and_ab+and_bc+and_ac )+xor_ab+xor_bc+xor_ac )/2;
int bc = 2*and_bc+xor_bc;
a[1] = abc-bc;
for(int i=2;i<=n;i++)
{
e[i] ^= e[i-1];
a[i] = e[i]^a[1];
}
cout << "! ";
for(int i=1;i<=n;i++) cout << a[i] << " ";
}
然后似乎遇到了瓶颈,因为在hard_version
中只允许使用
n
+
1
n+1
n+1次操作
上面的解法很难优化,不过还有条件,就是 a i ∈ [ 0 , n − 1 ] & & n < = 2 16 a_i\\in[0,n-1]\\&\\&n<=2^{16} ai∈[0,n−1]&&n<=216(且 n n n一定是 2 2 2的整次幂)
我们先询问所有 a i ⊕ a 1 a_i\\oplus a_1 ai⊕a1的值,这样只要没有出现两个值相等的情况或者值为零就没有重复数字
令 c i = a 1 ⊕ a i c_i=a_1\\oplus a_i ci=a1⊕ai
分情况讨论
①.若所有数字没有重复,那么必然是一个 [ 0 , n − 1 ] [0,n-1] [0,n−1]的排列
此时的异或结果必然恰好是落在 [ 0 , n − 1 ] [0,n-1] [0,n−1]
那么我们找到 c x = 1 c_x=1 cx=1,说明 a 1 a_1 a1和 a x a_x ax只有最低位不同,我们询问一次 A N D \\rm AND AND可以得到除了最低位的答案
我们再找到 c y = n − 2 c_y=n-2 cy=n−2,说明 a 1 a_1 a1和 a y a_y ay只有最低位相同,我们询问一次 O R \\rm OR OR可以得到最低位的答案
那么 a 1 a_1 a1求出来就做完了,刚好操作 n + 1 n+1 n+1次
②.若有重复,又分两种
一是 a 1 = a x a_1=a_x a1=ax,此时有 c x = 0 c_x=0 cx=0,那么询问一次 a 1 o r a x a_1\\rm or \\ a_x a1or ax即可
二是 a x = a y a_x=a_y ax=ay,此时有 c x = c y c_x=c_y cx=cy,此时询问 a x o r a y a_x \\rm or\\ a_y axor ay可以得到 a x a_x ax的值
那么就可以得到 a 1 a_1 a1的值
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e6+10;
int n,e[maxn],a[maxn],vis[maxn];
int OR(int l,int r)
{
cout << "OR " << l << " " << r << endl;
int x; cin >> x;
return x;
}
int XOR(int l,int r)
{
cout << "XOR " << l << " " << r << endl;
int x; cin >> x;
return x;
}
int AND(int l,int r)
{
cout << "AND " << l << " " << r << endl;
int x; cin >> x;
return x;
}
int main()
{
cin >> n;
for(int i=2;i<=n;i++) e[i] = XOR以上是关于1451E2 - Bitwise Queries (Hard Version)(交互,思维,位运算猜数组)的主要内容,如果未能解决你的问题,请参考以下文章
Kattis - bitwise Bitwise (RMQ+尺取+树上dfs)