P1100 高低位交换(橙色 普及-)
位运算, https://www.luogu.com.cn/problem/P1100
给出一个小于
例如,数
输入格式
一个小于
输出格式
将新的数输出。
输入输出样例 #1
输入 #1
1314520输出 #1
249036820这是一个经典的位运算问题。题目要求将一个 32 位无符号整数的高 16 位和低 16 位进行交换。
解题思路
- 数据类型选择: 由于输入的数最大可达到
,在 C++ 中 int类型(通常为 32 位带符号整数)会溢出。我们需要使用unsigned int(无符号 32 位整数)或者long long(64 位整数)来存储。 - 位运算原理:
- 高位移到低位:将原数右移 16 位 (
n >> 16)。这样原本在 [17-32] 位的数字就变成了 [1-16] 位。 - 低位移到高位:将原数左移 16 位 (
n << 16)。这样原本在 [1-16] 位的数字就变成了 [17-32] 位。由于是 32 位无符号操作,左移后高出的位会被自动舍弃(或者我们可以通过位掩码0xFFFFFFFF强制截断)。 - 合并结果:将上述两个结果进行“按位或” (
|) 操作即可得到交换后的新数。
- 高位移到低位:将原数右移 16 位 (
代码实现
cpp
#include <iostream>
using namespace std;
int main() {
// 使用 unsigned int 来处理 32 位无符号整数
// 在绝大多数现代编译器中,unsigned int 正好是 32 位
unsigned int n;
// 输入这个数
if (!(cin >> n)) return 0;
// (n >> 16) 将高 16 位移动到低 16 位的位置
// (n << 16) 将低 16 位移动到高 16 位的位置
// 两者进行位或运算,合并成新的 32 位数
unsigned int result = (n >> 16) | (n << 16);
// 输出结果
cout << result << endl;
return 0;
}逐步解析示例
以输入 1314520 为例:
- 二进制表示(32位):
0000 0000 0001 0100 0000 1110 1101 1000 - 右移 16 位 (
n >> 16): 高位变低位,前面补 0:0000 0000 0000 0000 0000 0000 0001 0100(十进制为 20) - 左移 16 位 (
n << 16): 低位变高位,后面补 0,原本的高位溢出丢弃:0000 1110 1101 1000 0000 0000 0000 0000(十进制为 249036800) - 按位或 (
|):0000 1110 1101 1000 0000 0000 0001 0100结果为249036800 + 20 = 249036820。
注意事项
- 如果在某些老旧环境下
unsigned int不是 32 位,可以使用<cstdint>头文件中的uint32_t。 - 如果使用
unsigned long long(64位),代码应改为((n & 0xFFFF0000) >> 16) | ((n & 0x0000FFFF) << 16)以确保只处理低 32 位。但在本题环境下,直接使用unsigned int是最简洁的做法。