C. Interesting Sequence

C. Interesting Sequence

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 (mn) 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?

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1t2000). The description of the test cases follows.

The only line of each test case contains two integers n, x (0n,x1018).

Output

For every test case, output the smallest possible value of m such that equality holds.

If the equality does not hold for any m, print 1 instead.

We can show that if the required m exists, it does not exceed 51018.

Example

input

5
10 8
10 10
10 42
20 16
1000000000000000000 0

output

12
10
-1
24
1152921504606846976

Note

In the first example, 10 & 11=10, but 10 & 11 & 12=8, so the answer is 12.

In the second example, 10=10, so the answer is 10.

In the third example, we can see that the required m does not exist, so we have to print 1.

 

解题思路

  首先遍历nx在二进制下的每一位,用nk来表示数字n二进制的第k位的数值,当遍历到第k位时发现nk=0xk=1,那么就必定无解。因为整个过程都是按位与的运算,如果nk=0,那么无论与什么数相与得到的结果都是0而不可能得到1

  接下来分类讨论:

  1. nk=0xk=0。那么m可以取任何数,最终nk & (n+1)k &  & mk=xk=0总是成立。
  2. nk=1xk=0。为了按位与后第k位为0,那么很明显应该让n加上某个数s(n+s)k=0,这样才能有nk & (n+1)k &  (n+s)k &  & mk=xk=0。很显然为了让n+s的第k位出现0s可以取到无穷大,因此我们来看看s最小可以取到多少。可以发现n的第k位要进位时才由变10,因此只用考虑由n的前k位所构成的数,即n % 2k+1,第k位进位后得到的结果为2k+1,因此s的最小值为2k+1n % 2k+1
  3. nk=1xk=1。为了按位与后第k位始终为1,那么在nm的数中不能出现第k位为0的数。一样的,当n的第k位要进位时才由变10,考虑由n的前k位所构成的数,即n % 2k+1,那么在进位前且第k位仍为1所能取到的最大值是2k+11,因此s的取值不应超过2k+11n % 2k+1

  然后对第2种情况的所有s取个最大值(即找到最大的下界)得到l,对第3种情况的所有s取个最小值(即找到最小的上界)得到r。如果lr说明有解,那么答案就是m=n+l;否则就是无解。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 void solve() {
 7     LL n, m;
 8     scanf("%lld %lld", &n, &m);
 9     LL l = 0, r = 9e18;
10     for (int i = 0; i < 60; i++) {    // 1e18的二进制位最多有60位
11         LL x = n % (1ll << i + 1);    // 得到n的前i位所构成的数
12         int a = n >> i & 1, b = m >> i & 1;
13         if (!a && b) {    // n的第k位为0,m的第k位为1,无解
14             printf("-1\n");
15             return;
16         }
17         if (a && !b) l = max(l, (1ll << i + 1) - x);    // 第一种情况
18         else if (a && b) r = min(r, (1ll << i + 1) - 1 - x);    // 第二种情况
19     }
20     printf("%lld\n", l <= r ? n + l : -1);
21 }
22 
23 int main() {
24     int t;
25     scanf("%d", &t);
26     while (t--) {
27         solve();
28     }
29     
30     return 0;
31 }
复制代码

 

参考资料

  Codeforces Round #843 (Div. 2) C (思维):https://zhuanlan.zhihu.com/p/598221402

posted @   onlyblues  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
Web Analytics
点击右上角即可分享
微信分享提示