1554C. Mikasa 按位枚举求最小值

题意

给正整数 n , m n,m nm,构造出 0 ⨁ n , 1 ⨁ n . . . . m ⨁ n 0\bigoplus n,1\bigoplus n....m\bigoplus n 0n,1n....mn,求此序列中未出现的最小数字。

解析

出现未出现的最小数字字眼,只要代换进公式即可,假设 k k k是出现过的数字, 设 0 < = x < = m 0<=x<=m 0<=x<=m

x ⨁ n = k x \bigoplus n =k xn=k
根据交换律
n ⨁ k = x < = m n \bigoplus k =x <=m nk=x<=m
也就是说,如果你出现过,你就会满足这个条件,因此我们加以转换
n ⨁ k > = m + 1 , k n \bigoplus k >= m+1,k nk>=m+1,k 的最小值就满足题意。
因此这个问题就转化成
n ⨁ k > = m + 1 = p n \bigoplus k>=m+1=p nk>=m+1=p

已知 n , p n,p n,p k k k的最小值
这个问题就实属典中点问题了。

我们画个图来解释,假设 n = 1010 ( 2 ) , p = 1101 ( 2 ) n=1010(2),p=1101(2) n=1010(2),p=1101(2)
w
由于 n ⨁ k > = p n \bigoplus k>=p nk>=p,因此第一位的n异或k我们必须为1

在这里插入图片描述

所以我们此时的k必须为0
在这里插入图片描述

同理,第二位的n异或k,必须为1,k也必须为1
在这里插入图片描述
第三位的时候,n异或k为1和为0都能满足公式,但是为了让我们的k尽可能小,因此我们选择n异或k为1,k=0,让我们的k尽可能地小。

在这里插入图片描述
第四位的时候也同理
在这里插入图片描述
所以我们就能根据从高位到低位的按位枚举从而求出k的最小值。
很典中典了。

但是当我们处在下面阶段的时候就没必要比较了,因为 n ⨁ k > = p n \bigoplus k>=p nk>=p已经永远成立,因此k的后面的位数所有取0就是最小的。
在这里插入图片描述

代码

#include<bits/stdc++.h>
using  namespace  std;
void solve(){
    int n,m;
    cin>>n>>m;
    int p=m+1,k=0;
    for(int i=30;i>=0;i--){
        int a=(n>>i)&1,b=(p>>i)&1;
        if(a!=b){
            if(b){//
                n|=(1<<i);//把答案存进n里面。
                k|=(1<<i);
            }
        }
        if(n>=p)break;//满足了条件了,我们就没必要再比较了
    }
    cout<<k<<endl;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值