CF1554C Mikasa

本蒟蒻的第一篇题解,如果有什么不足,请dalao轻喷。。。

题意

题目传送门

给出两个数 n n n m m m,求出最小的整数 p p p,使得 p p p ∉ \notin / { n ⊕ 1 , n ⊕ 2 , n ⊕ 3 , ⋅ ⋅ ⋅ , n ⊕ m n \oplus 1, n \oplus 2, n \oplus 3, ···, n \oplus m n1,n2,n3,⋅⋅⋅,nm } 。

思路

异或

先思考这道题之前,还不如先思考这道题目所要用的符号 ⊕ \oplus 有什么性质。

其中, ⊕ \oplus 的意思为:两个数在二进制状态下,各个数位对齐,位数不够就在前面补零,若两个数位相同就得 1 1 1,不同就得 0 0 0

比如:$12 \oplus 5 = $,列个竖式

1 1 1 1 1 1 0 0 0 0 0 0

⊕ \oplus 0 0 0 1 1 1 0 0 0 1 1 1

= = = 1 1 1 0 0 0 0 0 0 1 1 1

= = = 9 9 9

所以 12 ⊕ 5 = 9 12 \oplus 5 = 9 125=9,我们再举个例子:$12 \oplus 9 = $,不难得出答案为 5 5 5

因此,我们发现异或的一个性质 a ⊕ b = c a \oplus b = c ab=c,也可以转换为 a ⊕ c = b a \oplus c = b ac=b

解题

经过上面的推导,再看看题目,发现在程序中花括号中的数据可能会毫无规律,而且花括号中都有 n n n,于是我们考虑将式子转换为: n ⊕ p n \oplus p np ∉ \notin / { 1 , 2 , 3 , ⋅ ⋅ ⋅ , m 1, 2, 3, ···,m 1,2,3,⋅⋅⋅,m }

所以题目就可以转化为求一个最小的整数 p p p,使得 $ n \oplus p > m $。

当然,如果枚举出 p p p,时间肯定承受不了,所以只能构造出 p p p

分类讨论 :
  • n i = m i = 0 n_i = m_i = 0 ni=mi=0 p i = 0 p_i = 0 pi=0,因为 p p p 要最小,如果 p i = 1 p_i = 1 pi=1,虽然也能满足 n ⊕ p > m n \oplus p > m np>m,但是 p p p 不是最小的。
  • n i = 0 , m i = 1 n_i = 0, m_i = 1 ni=0,mi=1 p i = 1 p_i = 1 pi=1,同上。
  • n i = 1 , m i = 0 n_i = 1, m_i = 0 ni=1,mi=0 p i = 0 p_i = 0 pi=0, 且后面全为零,因为这个数为已经大于 m i m_i mi 的这一位了,后面的不管再怎么小也能满足题目要求。
  • n i = m i = 1 n_i = m_i = 1 ni=mi=1 p i = 0 p_i = 0 pi=0,同 1 1 1

Code

#include <cstdio>
#include <iostream>
using namespace std;

int n, m;

void Main() {
	cin >> n >> m;
	m++;
	int p = 0;
	for (int i = 30; i >= 0; i--) {
		if (((1 & (n >> i)) == 0) && ((1 & (m >> i)) == 1)) p = (1 << i) | p;
		if (((1 & (n >> i)) == 1) && ((1 & (m >> i)) == 0)) break;
	}
	cout << p << endl;
}

int main() {
	int T;
	for (cin >> T; T; T--) Main();
    return 0;
}
  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值