Codeforces Round #735 (Div. 2)-C. Mikasa-题解

36 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

@TOC

Codeforces Round #735 (Div. 2)-C. Mikasa

传送门 Time Limit: 1 second Memory Limit: 256 megabytes

Problem Description

You are given two integers nn and mm. Find the MEX\operatorname{MEX} of the sequence n0,n1,,nmn \oplus 0, n \oplus 1, \ldots, n \oplus m. Here, \oplus is the bitwise XOR operator.

MEX\operatorname{MEX} of the sequence of non-negative integers is the smallest non-negative integer that doesn't appear in this sequence. For example, MEX(0,1,2,4)=3\operatorname{MEX}(0, 1, 2, 4) = 3, and MEX(1,2021)=0\operatorname{MEX}(1, 2021) = 0.

Input

The first line contains a single integer tt (1t300001 \le t \le 30\,000) — the number of test cases.

The first and only line of each test case contains two integers nn and mm (0n,m1090 \le n, m \le 10^9).

Output

For each test case, print a single integer — the answer to the problem.

Sample Input

5
3 5
4 6
3 2
69 696
123456 654321

Sample Onput

4
3
0
640
530866

Note

In the first test case, the sequence is 30,31,32,33,34,353 \oplus 0, 3 \oplus 1, 3 \oplus 2, 3 \oplus 3, 3 \oplus 4, 3 \oplus 5, or 3,2,1,0,7,63, 2, 1, 0, 7, 6. The smallest non-negative integer which isn't present in the sequence i. e. the MEX\operatorname{MEX} of the sequence is 44.

In the second test case, the sequence is 40,41,42,43,44,45,464 \oplus 0, 4 \oplus 1, 4 \oplus 2, 4 \oplus 3, 4 \oplus 4, 4 \oplus 5, 4 \oplus 6, or 4,5,6,7,0,1,24, 5, 6, 7, 0, 1, 2. The smallest non-negative integer which isn't present in the sequence i. e. the MEX\operatorname{MEX} of the sequence is 33.

In the third test case, the sequence is 30,31,323 \oplus 0, 3 \oplus 1, 3 \oplus 2, or 3,2,13, 2, 1. The smallest non-negative integer which isn't present in the sequence i. e. the MEX\operatorname{MEX} of the sequence is 00.


题目大意

给你两个数nnmm,用所有00mm的数xx去异或nn

在得到的结果中,输出最小的未出现过的非负正整数。

解题思路

假设xn=kx\oplus n=k,那么根据异或的性质就有nk=xn\oplus k=x

我们可以尝试一些kk,用kk去异或nn,看得到的xx是否属于00~mm。如果属于,那么这个kk就能够被00~mm中的某个数异或nn来得到;如果不属于,那么这个kk就是00~mm中的数异或nn的所有结果中未出现过的。

所以现在就是在所有的异或nn之后的结果不属于00~mmkk中,找到最小的kk。问题转化为:找到最小的kk使得knm+1k\oplus n\geq m+1

接下来我们从高到低来看kk的每一位就行了。

想让kk最小,那么这一位能够是00的话绝不是11

如果nnm+1m+1的这一位nin_i(m+1)i(m+1)_i相同,那么kk的这一位就可以是00,因为0ni=ni=(m+1)i(m+1)i0\oplus n_i = n_i = (m+1)_i\geq(m+1)_i

如果ni(m+1)in_i\neq (m+1)_i

如果nin_i11(m+1)i(m+1)_i00,那么kik_i可以是00,因为kini=01=1>0=(m+1)ik_i\oplus n_i=0\oplus1=1>0=(m+1)_i

如果nin_i00(m+1)i(m+1)_i00的话,那么kik_i必须是11,否则kini=00k_i\oplus n_i=0\oplus0<(m+1)i<(m+1)_i了。

任何时刻,一旦knk\oplus n已经>m+1>m+1了,kk剩下的位都为00就可以了,之间breakbreak掉就行。

具体实现可以再参考一下代码。


AC代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int main()
{
    int N;
    cin>>N;
    while(N--)
    {
        int n, m;
        cd(n), cd(m); // scanf n、m
        m++; // m 变成 m+1
        int k=0; // 答案k的初始值为0(越小越好)
        for(int i=30;i>=0;i--) // 枚举每一位
        {
            int thisN=n>>i&1; // n的这一位
            int thisM=m>>i&1; // m的这一位
            if(thisN!=thisM)  // 如果相等就什么都不需要做,如果不相等:
            {
                if(thisN==0) // 如果n的这一位是0(说明m的这一位是1),那么k的这一位必须是1
                {
                    k+=1<<i;
                }
            }
            if((n^k)>=m)break; // 一旦n异或k已经大于等于m了(现在的m是输入的m+1),就退出
        }
        cout<<k<<endl; // 输出k即可
    }
    return 0;
}

前面想歪了

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:letmefly.blog.csdn.net/article/det…