51nod 3047位运算(and 和 xor)位移运算
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 3047位运算(and 和 xor)位移运算相关的知识,希望对你有一定的参考价值。
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");
以上是关于51nod 3047位运算(and 和 xor)位移运算的主要内容,如果未能解决你的问题,请参考以下文章