Codeforces Round #735 (Div. 2)_C. Mikasa

C. Mikasa

题目传送门:

题目传送门

题面:

在这里插入图片描述

题目大意:

这什么位运算场。
给你 n , m n,m n,m,让你求 n ⊕ 0 , n ⊕ 1... n ⊕ m {n⊕0,n⊕1...n⊕m} n0,n1...nm中最小未出现的非负数。

运算法则:

a ⊕ a = 0
a ⊕ b = b ⊕ a(交换律)
a ⊕b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c; (结合律)
d = a ⊕ b ⊕ c 可以推出 a = d ⊕ b ⊕ c.
a ⊕ b ⊕ a = b.
A ⊕ 0 = A ;
1异或任何数,其结果=任何数取反;
任何数异或自己,等于把自己置0

思路:

如果存在y, n ⊕ x = y n⊕x=y nx=y 0 ≤ x ≤ m 0≤x≤m 0xm
可以转化 n ⊕ x = y n⊕x=y nx=y n ⊕ y = x n⊕y=x ny=x
0 ≤ x ≤ m 0≤x≤m 0xm

所以原问题,找最小非负且不为y的数。
转化为找到最小的非负k,满足 n ⊕ k ≥ m + 1 n⊕k≥m+1 nkm+1

设m+1=p;
n ⊕ k ≥ p n⊕k≥p nkp!!!

考虑从高位往低位构造。

  1. n i = = p i n_i==p_i ni==pi k i = 0 k_i=0 ki=0,保证 n i = = p i n_i==p_i ni==pi,也可以达成 n = = p n==p n==p
  2. n i = 1 , p i = 0 n_i=1,p_i=0 ni=1,pi=0 k i = 0 k_i=0 ki=0即可。此时已满足 n i ⊕ k i ( 1 ) ≥ p i ( 0 ) n_i⊕k_i(1)≥p_i(0) niki1pi0,直接进行一个break
  3. n i = 0 , p i = 1 n_i=0,p_i=1 ni=0,pi=1,则此时 k i k_i ki必须==1,否则结果的这一位就比p的这一位小了,之后一定 n ⊕ k ≤ p n⊕k≤p nkp

想通了还是不难的。

代码:



#include<bits/stdc++.h>

using namespace std;
typedef long long ll;

int main() {
    int T;
    cin >> T;
    while (T--) {
        int n, m;
        cin >> n >> m;
        if (m + 1 <= n) {
            //0异或a=a
            //要找到最小k,满足n异或k≥m+1
            //也就是满足n异或k>m
            cout << 0 << endl;
            continue;
        }
        m++;
        int k = 0;
        for (int i = 30; i >= 0; i--) {
            int x = n >> i & 1;
            int y = m >> i & 1;
            //取二进制每一位
            if (x == y) continue;
            //k这一位为0;
            if (y) {
                k ^= 1 << i;
                n ^= 1 << i;
                //k这一位为1
            }
            if (n >= m) break;
            //n存了结果
        }
        cout << k << endl;
    }
    return 0;
}

他人代码

    while (T--) {
        int n, m;
        cin >> n >> m;
        int ans = 0;
        m++;
        for (int i = 30; i >= 0; i--) {
            if (((1 << i) & m) && !((1 << i) & n))ans += 1 << i;
            //更简洁,pi==1&&ni==0,那么ki==1;
            //否则后面几位变化改变不了高位已经比p小
            else if (!((1 << i) & m) && ((1 << i) & n))break;
            //一样直接不处理
            //pi==0&&ni==1,满足条件了,跳出就行。
        }
        cout << ans << endl;
    }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值