首先我们为了更好的了解这些位运算的运算过程和原理,我们得先明白进制之间的转化。
首先我们得知道十进制与二进制之间的转化。
进制转化:
在这里举两个例子
183:1 0 1 1 0 1 1 1
98:1 1 0 0 0 1 0
转化代码:
int a[10000];
int t = 183;//98
int cnt = 0;
while (t)//有两种方法,任选一种即可
{
/* if (t & 1)//t为奇,相当于t%2==1
{
a[cnt++] = 1;
}
else
{
a[cnt++] = 0;
}
t /= 2;*/
a[cnt++] = t % 2;
t /= 2;
}
reverse(a, a + cnt);//倒置数组。
将一串二进制转化为十进制数字,如下:
(从右往左的以2为底,各数字对应的位权次方(0开始)乘以该数组位置上的数,其总和即为十进制最终得数)
int sum = 0;
int o = 0;
for (int i = cnt-1;i>=0;i--)
{
sum += pow(2, o++) * a[i];
}
cout << sum << endl;
&(按位与)运算 AND:
&:相同则同,否则0。
183:1 0 1 1 0 1 1 1
98: 1 1 0 0 0 1 0
183&98=34。
34: 1 0 0 0 1 0
由按位运算规则可以知道,任何数&1,不是0就是1。所以我们可以通过这一点来判断一个数的奇偶性。用 (x&1) 来代替 (x%2==1)。
^(按位异或)运算 XOR:
^:相同为0,不同为1
183:1 0 1 1 0 1 1 1
98: 1 1 0 0 0 1 0
183^98=213。
213: 1 1 0 1 0 1 0 1
由上述可知,任何二进制数与零异或,都会等于其本身,即 A ^ 0 = A。
异或性质
(1)交换律: A ^ B = B ^ A
(2)结合律: ( A ^ B ) ^ C = A ^ ( B ^ C )
(3)自反性: A ^ B ^ B = A (由结合律可推: A ^ B ^ B = A ^ ( B ^ B ) = A ^ 0 = A)
这里我们就多出一种交换两个数而不使用中间变量的方法:
a = a ^ b; // a = 3 ^ 7
b = a ^ b; // b = (3 ^ 7) ^ 7 = 3 ^ (7 ^ 7) = 3
a = a ^ b; // a = (3 ^ 7) ^ (3 ^ 7 ^ 7) = (3 ^ 3) ^ (7 ^ 7) ^ 7 = 7
|(按位或) OR:
|:有1则1。无则0;
183:1 0 1 1 0 1 1 1
98: 1 1 0 0 0 1 0
183|98=247。
247: 1 1 1 1 0 1 1 1
~(取反):
183:1 0 1 1 0 1 1 1
~183: 0 1 0 0 1 0 0 0
>>(右移):
183:1 0 1 1 0 1 1 1
其功能是把“>> ”左边的运算数的各二进位全部右移若干位, “>>”右边的数指定移动的位数。
右移相当于该数除以2的n次方,前提是数据不能丢失。
183>>2:0 0 1 0 1 1 0 1 =45。
<<(左移):
183:1 0 1 1 0 1 1 1
其功能是把“>> ”左边的运算数的各二进位全部右移若干位, “>>”右边的数指定移动的位数。
左移相当于该数乘以2的n次方,前提是数据不能丢失。
183<<2:1 0 1 1 0 1 1 1 0 0 = 732
lowbit函数:
之前在cf上遇到过一个题目:Problem - C - Codeforces
问到一个数n & (n+1) & … & m=x,需要按位到多少才能等于x,当然,这个x一定会比n小
其中学到了一个lowbit函数:
用来取一个二进制最低位的一与后边的0组成的数
比如:5(101),lowbit(5)=1(1)
12(1100),lowbit(12)=4(100)
在这里换言之其中的作用是返回刚好能够改变二进制最后一个1(使之变为0)的十进制整数。
ll lowbit(ll x)
{
return x & (-x);//x&(~x+1)
}
其中(-x)=(~x+1)其实就是x+~x=-1的前身,换个位置就好了。
#include<math.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<map>
#include<list>
#include<string>
#include<queue>
#include<set>
#include<vector>
#include<stack>
#include<limits>
#define re register
#define iosgo() std::ios::sync_with_stdio(false),std::cin.tie(nullptr),std::cout.tie(nullptr);
#define run(i,n) for (int i = 1; i <= n; i++)
#define cin std::cin
#define cout std::cout
#define ll long long
#define endl "\n"
using namespace std;
typedef pair<int, int>pll;
inline ll read()
{
ll x = 0, w = 1; char ch = getchar();
for (; ch > '9' || ch < '0'; ch = getchar())if (ch == '_')w = -1;
for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x * w;
}
ll lowbit(ll x)
{
return x & (-x);//x&(~x+1)
}
void solve()
{
ll n, x;
n = read(); x = read();
if (x > n)
{
cout << "-1\n"; return;
}
if (n == x)
{
cout << n << endl; return;
}
while (n >= x)
{
ll temp;
temp = n + lowbit(n);
n &= temp;
if (n == x)
{
cout << temp << endl;
return;
}
}
cout << "-1\n";
}
int main()
{
int t;
t = read();
while (t--)
{
solve();
}
}