传送门:CF
题目描述:
Petya and his friend, robot Petya++, like to solve exciting math problems.
One day Petya++ came up with the numbers n and x and wrote the following equality on the board:
n & (n+1) & … & m=x,
where & denotes the bitwise AND operation. Then he suggested his friend Petya find such a minimal
m (m≥n) that the equality on the board holds.
Unfortunately, Petya couldn't solve this problem in his head and decided to ask for computer help. He
quickly wrote a program and found the answer.
Can you solve this difficult problem?
输入:
5
10 8
10 10
10 42
20 16
1000000000000000000 0
输出:
12
10
-1
24
1152921504606846976
赛场上的做法假了,一直挂在一个点上,感觉还是自己前面的题做的太慢了,导致这道题时间并不充裕,然后慌起来之后脑子也比较混乱.赛后感觉这道题也并不是很难…
主要思路:
- 首先我们把玩一下我们的题目,我们会发现原来的式子n&(n+1)&…&m=xn\&(n+1)\& … \&m=xn&(n+1)&…&m=x有一个比较显然的性质,那就是我们&\&&的越多,我们的式子显然是越小的.因为我们的之前的二进制1会因为后面的0变成0,但是并不会有新的1出现,所以肯定是越变越小的
- 所以一个比较简单的枚举区间就出来了,那肯定就是一直进行&\&&运算,然后到式子的值比x还要小的时候如果还没有和x相等过的话,肯定就不可能再相等了,直接输出-1即可,但是直接一个一个枚举肯定是不行的,必超时,所以我们需要进行一点点优化.
- 我们把玩一下我们的二进制式子和我们的&\&&运算.我们会发现因为二进制1后面的0存在,所以我们的二进制位最后一个1后面的数字再变化就没有意义,并不会改变我们的所有式子,讲起来可能比较抽象,举一个简单的栗子:
1010101000
比如上面的这个二进制数字,假设当前我们的式子最终的数字是这个,那么此时我们给他+1,+2,+3+1,+2,+3+1,+2,+3等等都是没有任何意义的,因为加的数字只贡献最后一个1后面的0的数字,和我们的0与起来依旧是0.那么加多少才有意义呢,我们会发现需要一直加到(1000)这个数字才会发生改变,而这个数字恰好是我们最后一个1形成的二进制数!!
至于如何找到我们的二进制位中的最后一个1,我们有一个比较模板的写法,称之为lowbit函数lowbit函数lowbit函数,这个函数在树状数组中会使用到,网上博客介绍得到也十分详细,此处就不再赘述了
下面是具体的代码部分:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
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;
}
#define int long long
#define maxn 1000000
const double eps=1e-8;
#define int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int t;
int n,x;
int lowbit(int x) {return x&(~x+1);}
signed main() {t=read();while(t--) {n=read();x=read();if(x>n) {printf("-1\n");continue;}if(x==n) {printf("%lld\n",x);continue;}int flag=0;while(n>=x) {int temp=n+lowbit(n);n&=temp;if(n==x) {printf("%lld\n",temp);flag=1;break;}}if(flag==0) printf("-1\n");}return 0;
}