【51nod 3047】【位运算】(and 和 xor)位移运算

3047 位移运算

51nod 3047 位移运算


题目

给出两个数a,b。问a能否只通过位移运算( >>和 << 可以多次使用)变成b。如果可以输出"Yes",否则输出"No"。

输入
第一行:一个数 t ( 1≤t≤100000)。
第2 ~ t+1行:每行2个a,b中间用空格分隔(0≤a, b≤10^9)。
输出
输出共t行,对应答案的"Yes"和"No"
数据范围
对于20%的数据,1≤t≤50,0≤a, b≤20;
对于40%的数据,1≤t≤2000;
对于100%的数据,1≤t≤100000,0≤a, b≤10^9;
输入样例

4
4 2
2 4
3 4
1 3

输出样例

Yes
Yes
Yes
No

解题思路

位移可以去除两边01也可以增加两边0,但是却不能增加1,那么想要 a 变成 b,就要在a中找到b串
比如11011011 肯定不能变成 111,但是10111010却可以

因为10 ^ 9次其实也就 30 位二进制,所以可以枚举 b 在 a 的哪个位置, 从后往前枚举,每次用移位删去a的最后一位
a & b 如果可以等于 b,表明 b 中为 1 的位置在 a 中也为 1

但是还有特殊情况
a = 10011, b = 10001, a & b = 10001 = b,但显然 a 不能变成 b,b也不是 a 的子串
为什么会有这种情况,因为 b 中有 0,而 a 的同位置上是1
用异或来解决👇

如果出现上述情况,那就一定在二进制中间有一个位置异或出来是1
c = a ^ b = 10
但是如果没有上述情况,异或出来的结果是什么,比如10111010,111
假设现在已经枚举到正确的位置 a = 10111, b = 111
那么c = a ^ b = 10000
在正确位置时,b 是 a 的后缀,c 异或出来一定是 a 去掉 b 串的前缀,那么 c 要么等于0,要么就一定比 b 大
所以解决方案就是看异或值是不是比 b 大就行了


Code

#include <bits/stdc++.h>

using namespace std;

int a, b, c, T;

int lowbit(int x) { return (x & -x); }

int main() {
	scanf("%d", &T);
	while(T --) {
		scanf("%d %d", &a, &b);
		if(b == 0) {
			printf("yes\n");
			continue;
		}
		while((b & 1) == 0) b >>= 1;
		int flag = 0;
		for(; a >= b; a >>= 1) {
			if((b & a) != b) continue;
			c = lowbit(a ^ b);
			if(c < b && c > 0) continue;
			flag = 1; break;
		}
		if(flag) printf("yes\n");
			else printf("no\n");
	}
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值