高低位交换

GitHub跳转原题关系图返回列表

用掩码取出低 16 位并左移,同时把高 16 位右移,再按位或合并。

OJ: luogu

题目 ID: P1100

难度:普及-

标签:位运算掩码python

创建: 2026-07-16 19:20

更新: 2026-10-07 10:17

题意

把一个 32 位无符号整数的高 16 位与低 16 位交换,输出新整数。

思路

number>>16 把高半部分移动到低位;number&0xFFFF 只保留低 16 位,再左移 16 位。两部分没有重叠,用按位或合并:

text
(number >> 16) | ((number & 0xFFFF) << 16)

Python 知识

  • 十六进制字面量 0xFFFF 正好是 16 个二进制 1。
  • & 是按位与掩码,<<、>> 是位移,| 合并位段。
  • Python 整数没有固定 32 位,但输入范围保证上述结果与无符号 32 位运算一致。
  • 一行表达式已完整表达算法,不需要额外函数。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/cpp_to_python_pitfalls.md:Python 与 C++ 固定位宽整数差异。

代码

python
number = int(input())
print((number >> 16) | ((number & 0xFFFF) << 16))
cpp
/**
 * P1100 高低位交换
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */

#include <bits/stdc++.h>
using namespace std;

int main() {
    unsigned int n;
    scanf("%u", &n);
    // 低 16 位左移、高 16 位右移,然后合并
    unsigned int ans = (n >> 16) | (n << 16);
    printf("%u\n", ans);
    return 0;
}

Pythonic 写法

位运算高低互换:

python
x = int(input())
print((x >> 16) | ((x & 0xFFFF) << 16))

STL 写法

把整数装进 bitset<32> 后每一位都有确定的下标:下标 0 是最低位,下标 31 是最高位,于是「高 16 位」就是下标 16…31、「低 16 位」是下标 0…15。bits << 16 把低半段顶到高位、bits >> 16 把高半段落回低位,两段互不重叠,按位或合并就完成了交换,最后用 to_ulong() 转回十进制输出。和上面 main.cpp 直接对整数做掩码位移相比,这里不必手写 0xFFFF,位段的位置由下标直接说明;读入用 unsigned long long,因为输入可能达到 232−12^{32}-1,超出 int 的范围。

对应的 cppbook 章节:bitset:一组二进制开关

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-07 00:22
 * update_at: 2026-10-07 00:35
 */
// 这是 STL 写法:把 32 位整数装进 bitset<32>,用 (b << 16) | (b >> 16) 交换高低 16 位,
// 再用 to_ulong() 转回十进制输出。对应 cppbook 的《bitset:一组二进制开关》。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

unsigned long long number; // 输入可能达到 2^32-1,超过 int,所以用 unsigned long long 读入

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> number;

    // bitset<32> 把整数摊成 32 个开关:下标 0 是最低位,下标 31 是最高位。
    // 题面说的“前 16 位(高位)”正是下标 16..31,“后 16 位(低位)”是下标 0..15。
    bitset<32> bits(number);

    // 左移 16 位把低 16 位顶到高位,右移 16 位把高 16 位落回低位;
    // 两段互不重叠,按位或合并就完成了交换。移出 32 位宽度的位直接丢弃,不影响结果。
    bitset<32> swapped = (bits << 16) | (bits >> 16);

    // 转回整数输出十进制。32 位值一定能被 unsigned long 表示,不会触发 overflow_error。
    unsigned long answer = swapped.to_ulong();
    cout << answer << '\n';

    return 0;
}

复杂度

固定次数位运算,时间和额外空间复杂度均为 O(1)O(1)。

总结

位段操作的标准步骤是“掩码取出、位移到位、按位或合并”。