题解:位运算
题解:位运算
本题我们可以使用左移运算符
<<
和右移运算符>>
来求解本题。这里先给不熟悉这两个运算符的同学做一个详细的前置知识讲解,熟悉的同学可以跳过
1.右移运算符:
>>
定义:右移运算符将一个整数的二进制表示向右移动指定的位数,左侧空出的位置根据数据类型填充。
语法
C++/Java/Python
result = value >> n
value
:要进行右移操作的整数。n
:右移的位数。result
:右移后的结果。作用
- 每次右移一位,相当于将数值除以 (向下取整)。
- 右移位相当于将数值除以。
例如,,二进制表示为,就会导致最右边的消失,二进制表示变为,对应的十进制数为,右移两位就会导致最右边的和消失,二进制表示变为,对应的十进制数为
应用场景
- 场景1:快速计算的商(向下取整)。
- 场景2:提取二进制数的特定位(通常需要和
&
运算符结合使用)在实际的笔试中,场景2是出现最多的,在二进制枚举、数论中的相关算法题都会遇到。
2.左移运算符
<<
定义:左移运算符将一个整数的二进制表示向左移动指定的位数,右侧空出的位置用 填充
语法
C++/Java/Python
result = value << n
value
:要进行左移操作的整数。n
:左移的位数。result
:左移后的结果。作用
- 每次左移一位,相当于将数值乘以。
- 左移位相当于将数值乘以。
例如,,二进制表示为,就会往最右边补一个,二进制表示变为,对应的十进制数为,左移两位就会往最右边补两个,二进制表示变为,对应的十进制数为
应用场景
- 场景1:快速计算 的倍数。
- 场景2:在位掩码操作中生成特定的位模式(通常需要和
|
运算符结合使用)在实际的笔试中,场景1一般不怎么遇到,因为可以借助快速幂算法来更快地计算,场景2是使用的非常多的,尤其是在数论问题中,经常会遇到。
(x>>i)&1
就可以获得二进制表示的第位,我们根据题意使用>>
运算符计算即可。如果第位为,我们则需要累加上,这就可以借助
<<
运算符来实现。我们根据题意模拟即可,过程如下:
步骤1:使用右移运算符
>>
提取和的第位。步骤2:构造结果 :
- 将 的第位作为高位,插入到的第位。
- 将 的第位作为低位,插入到的第位。
- 使用左移运算符
<<
和按位或运算符|
完成插入操作,如果不想使用按位或运算符|
,也可以直接使用加法+
将结果累加。C+
#include<bits/stdc++.h> using namespace std; // 定义无符号整型类型 typedef unsigned long long ull; int main() { int n; cin >> n; // 输入数据组数 while (n--) { unsigned int x, y; cin >> x >> y; // 输入两个无符号4字节整数 ull z = 0; // 初始化结果z为0 // 按照zorder规则逐位计算 for (int i = 0; i < 32; ++i) { // 从x和y中分别取第i位 int bit_x = (x >> i) & 1; // 取x的第i位 int bit_y = (y >> i) & 1; // 取y的第i位 // 将x的第i位作为高位,y的第i位作为低位,插入到z中 z += (ull)bit_x << (2 * i + 1); // 插入高位 z += (ull)bit_y << (2 * i); // 插入低位 } cout << z << endl; // 输出z值 } return 0; }
Java
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); // 输入数据组数 while (n-- > 0) { int x = scanner.nextInt(); // 输入第一个无符号4字节整数 int y = scanner.nextInt(); // 输入第二个无符号4字节整数 long z = 0; // 初始化结果z为0 // 按照zorder规则逐位计算 for (int i = 0; i < 32; ++i) { // 从x和y中分别取第i位 int bit_x = (x >> i) & 1; // 取x的第i位 int bit_y = (y >> i) & 1; // 取y的第i位 // 将x的第i位作为高位,y的第i位作为低位,插入到z中 z |= (long) bit_x << (2 * i + 1); // 插入高位 z |= (long) bit_y << (2 * i); // 插入低位 } System.out.println(z); // 输出z值 } scanner.close(); } }
Python(pypy)
使用Python3提交会有两个样例超时哦,笔试还是推荐pypy提交。
# 输入数据组数 n = int(input()) while n > 0: n -= 1 # 输入两个无符号4字节整数 x, y = map(int, input().split()) z = 0 # 初始化结果z为0 # 按照zorder规则逐位计算 for i in range(32): # 从x和y中分别取第i位 bit_x = (x >> i) & 1 # 取x的第i位 bit_y = (y >> i) & 1 # 取y的第i位 # 将x的第i位作为高位,y的第i位作为低位,插入到z中 z |= bit_x << (2 * i + 1) # 插入高位 z |= bit_y << (2 * i) # 插入低位 print(z) # 输出z值