题目大意:给出两正数n,x,要求找出一最小的整数m使n&(n+1)&...&m=x
0<=n,x<=1e18
思路:因为几个数连&不可能有更多的1出现在二进制表达中,所以我们的目的就是要让n中所有的1与x中的1同位置的保留,不同位置的消去,那么x中是1的位置n也必须是1,否则m不存在,然后我们发现只要将最大的不同位置为0,下一位置为1,就能实现消去这个位置以及之前所有的1,所以要想m存在,我们首先要最大的不同位置大于最小的要保留位置,同时最大的不同位置的下一位必须是0,
//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mpow(ll a, ll b)
{//求a的b次方
ll temp = a;
for (int i = 1; i <= b - 1; i++)
{
a *= temp;
}
return a;
}
int main()
{
int t;
cin >> t;
while (t--)
{
ll n, x;
cin >> n >> x;
if (n == x)
{//特判两数一开始就相等
cout << n << endl;
continue;
}
vector<int>a, b(70, 0);//分别存a和b的二进制表达,b要全部初始化为0,因为n可能位数比x
多
int itb = 0;
while (x)
{//十进制转二进制
if (x & 1)
{
b[itb] = 1;
}
itb++;
x >>= 1;
}
while (n)
{//十进制转二进制
if (n & 1)
{
a.push_back(1);
}
else
a.push_back(0);
n >>= 1;
}
bool flag = 1;
int mi = 70;//最小的需要保留位置
for (int i = 0; i <= b.size() - 1; i++)
{
if (b[i] == 1 && (i>=a.size()||a[i] != 1))
{//如果x的这个位置是1但n不是,m不存在
flag = 0;
break;
}
if (mi == 70 && b[i] == 1)
{
mi = i;
}
}
int ma = -1;//最大需要置反的位置
for (int i = a.size() - 1; i >= 0; i--)
{//从后向前遍历
if (ma == -1 && b[i] == 0 && a[i] == 1)
{//x当前位置是0,n当前位置是1
ma = i;
break;
}
}
a.push_back(0);//放一个无用元素防止越界
if (ma > mi || a[ma + 1] == 1 && b[ma + 1] == 1)
flag = 0;
if (!flag)
{
cout << -1 << endl;
continue;
}
ll ans = 0;
for (ll i = 0; i <= b.size() - 1; i++)
{
if (b[i] || i == ma + 1)
{//x中是1的位置和最大需要置反的位置的下一位
ans += mpow(2, i);
}
}
cout << ans << endl;
}
return 0;
}