位运算呗

位运算

位运算,基础运算(CSP要考哦)

运算符
& 如果两个相应的二进制位都为 (1) ,则该位的结果值为 (1) ,否则为 (0)
| 两个相应的二进制位中只要有一个为 (1) ,该位的结果值为 (1)
^ 异或 若参加运算的两个二进制位值相同则为 (0) ,否则为 (1)
~ ~是一元运算符,用来对一个二进制数按位取反,即将 (0) 变 (1) ,将 (1) 变 (0)
<< 用来将一个数的各二进制位全部左移 (N) 位,右补 (0)
>> 将一个数的各二进制位右移 (N) 位,移到右端的低位被舍弃,对于无符号数,高位补 (0)

注意,异或优先级高于或哦

与的特殊用法

1.判断奇偶(速度比%2要快)

N&1==1,说明为奇数,若为0,则说明为偶数;

2.异或翻转二进制

将对应的位数异或1即可。

3.寻找最低位“1”

例如n,n&(-n)就是最低位的“1”所代表的数,如110(2进制)找出来就是4(10进制)

4.<<与>>求2次幂

k<<n=k*2的n次方

k>>n=k/2的n次方

5.常用位运算的技巧

用途
n&(n−1)==0 判断一个数是否为 2 的幂
n&(−n) 获得一个数二进制的最后一个为 1的bit
n&((1<<x)−1) 求 n mod 2x
(x xor y)>=0 判断两个数符号是否相同

以下为我认为有思维难度的题目

1.位移运算

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

输入格式

第一行:一个数 t ( 1≤t≤100000)。 第2 ~ t+1行:每行2个a,b中间用空格分隔(0≤a, b≤10^9)。

输出格式

输出共t行,对应答案的"Yes"和"No"

输入样例
4
4 2
2 4
3 4
1 3

输出样例

Yes
Yes
Yes
No

数据范围

对于20%的数据,1≤t≤50,0≤a, b≤20; 对于40%的数据,1≤t≤2000; 对于100%的数据,1≤t≤100000,0≤a, b≤10^9;

思路:

先来分析一下位移操作可以做什么。

  1. 使用 <<去掉当前数的高位的 1 。
  2. 使用 >>去掉当前数的低位的 1。

所以位移操作只能够去掉 a 中高位或低位的 1 。当然在去掉 1 后,我们可以通过反向位移,相当于将原本在低位或高位的 1 变为 0 。

如果 a 可以变成 b ,则去掉 b 的前导 0 和尾部的 0 (暴力第一个 1 和最后一个 1 )。得到的 0101 串 b′b′ 一定是 a 的子串。

我们可以利用 && 和 lowbit 来快速判断b′ 是否为 a 的子串。方法如下:

去掉 b 尾部的 0 得到 b′ 。

利用循环对 a 进行 >> 操作得到 a′a′ ,如果 b′ & a′=b′ ,则表明所有 b′ 为 1 的位, a′ 在相同位置的值也是 1 。r然而这还不是 b′ 为 a′ 子串的充分条件,因为还存在这种情况:

10011 & 10001=10001 。但后者不是前者的子串。

我们还要看 a′ xor b′ 得到的 c ,如果 c 最后一个 1 比 b′ 最高位的 11 位置更高,才表明b′ 为a′ 的子串。

例如:

10011 & 10001=10001 ,110011 xor 10001=100010 。

获取最低位的 1 得到 10 。 10<10001 所以不是子串。

利用这两个方法,就可以快速的判断 a 是否能够通过位移操作变成 b 了。

说白了,就是判断01子集是否相同,用位运算处理一切变换即可

实现代码:(未完待续)

posted @ 2023-04-10 16:51  铃狐sama  阅读(63)  评论(0)    收藏  举报