题解:位运算

题解:位运算

本题我们可以使用左移运算符<<和右移运算符>>来求解本题。

这里先给不熟悉这两个运算符的同学做一个详细的前置知识讲解,熟悉的同学可以跳过

1.右移运算符:>>

定义:右移运算符将一个整数的二进制表示向右移动指定的位数,左侧空出的位置根据数据类型填充。

语法

C++/Java/Python

result = value >> n
  • value:要进行右移操作的整数。
  • n:右移的位数。
  • result:右移后的结果。

作用

  • 每次右移一位,相当于将数值除以 22(向下取整)。
  • 右移nn位相当于将数值除以2n2^n

例如,x=6x=6,二进制表示为110110x>>1x>>1就会导致最右边的00消失,二进制表示变为1111,对应的十进制数为33,右移两位x>>2x>>2就会导致最右边的0011消失,二进制表示变为11,对应的十进制数为11

应用场景

  • 场景1:快速计算2n2^n的商(向下取整)。
  • 场景2:提取二进制数的特定位(通常需要和&运算符结合使用)

在实际的笔试中,场景2是出现最多的,在二进制枚举、数论中的相关算法题都会遇到。

2.左移运算符<<

定义:左移运算符将一个整数的二进制表示向左移动指定的位数,右侧空出的位置用 00 填充

语法

C++/Java/Python

result = value << n
  • value:要进行左移操作的整数。
  • n:左移的位数。
  • result:左移后的结果。

作用

  • 每次左移一位,相当于将数值乘以22
  • 左移nn位相当于将数值乘以2n2^n

例如,x=6x=6,二进制表示为110110x<<1x<<1就会往最右边补一个00,二进制表示变为11001100,对应的十进制数为23+22=122^3+2^2=12,左移两位x<<2x<<2就会往最右边补两个00,二进制表示变为1100011000,对应的十进制数为24+23=242^4+2^3=24

应用场景

  • 场景1:快速计算 2n2^n 的倍数。
  • 场景2:在位掩码操作中生成特定的位模式(通常需要和|运算符结合使用)

在实际的笔试中,场景1一般不怎么遇到,因为可以借助快速幂算法来更快地计算,场景2是使用的非常多的,尤其是在数论问题中,经常会遇到。

(x>>i)&1就可以获得xx二进制表示的第ii位,我们根据题意使用>>运算符计算即可。

如果第ii位为11,我们则需要累加上2i2^i,这就可以借助<<运算符来实现。

我们根据题意模拟即可,过程如下:

步骤1:使用右移运算符 >> 提取xxyy的第ii位。

步骤2构造结果zz

  • xx 的第ii位作为高位,插入到zz的第2i+12i+1位。
  • yy 的第ii位作为低位,插入到zz的第2i2i位。
  • 使用左移运算符 << 和按位或运算符 | 完成插入操作,如果不想使用按位或运算符|,也可以直接使用加法+将结果累加。

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值
相关面经
全部面经
招聘动态
更多动态