牛客网NC277217:异或故事(位运算妙用)
问题描述
来自牛客网题号NC277217的一道有趣的位运算题目。
给定t
组询问,每次询问都会给出一个正整数a
,需要在区间[1, 10^9]
中找到两个正整数b
和c
,使得b⊕c=a
。(⊕表示按位异或)
输入输出格式
输入格式:
- 第一行输入一个整数
T (1≤T≤10^5)
表示数据组数 - 每组测试数据一行,输入一个整数
a (1≤a≤10^9)
输出格式:
- 对于每组测试数据,输出两个正整数,表示找到的
b
和c
- 如果存在多个解决方案,可以输出任意一个
解题思路
这道题看似复杂,实际上有一个简单的数学性质可以利用:对于任意正整数a
,总能找到两个正整数b
和c
使得b⊕c=a
。
为什么呢?因为异或运算有如下性质:
- 如果
b⊕c=a
,那么c=a⊕b
- 当
1≤b≤10^9
时,只要保证a⊕b
也在区间[1, 10^9]
内,我们就找到了一组解
最简单的方法是,可以从b=1
开始尝试,计算c=a⊕b
,检查c
是否合法(即在范围内且满足条件)。由于异或的特性,一定能找到满足条件的解。
代码实现
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int a,b,c;
cin>>a;
for(b=1;b<=1e9;b++){
c=a^b;//c = a ^ b:通过异或计算c的值(按位异或特性)
if(b^c==a&&c>0&&c<=1e9){
cout<<b<<" "<<c<<endl;//分别输出b,c的值。
break;
}
}
}
return 0;
}
代码解析
- 读入测试用例数量
t
- 对于每个测试用例:
- 读入整数
a
- 从
b=1
开始尝试,计算c=a^b
- 检查
b^c==a
是否成立(这是必然的,因为c=a^b
意味着b^c=b^(a^b)=a
,但为了代码的严谨性仍进行了验证) - 同时检查
c
是否在合法范围内:c>0 && c<=1e9
- 一旦找到满足条件的
b
和c
,输出结果并结束当前测试用例
- 读入整数
优化思路
其实,我们可以证明,对于任意的a
,如果选择b=1
,那么c=a^1
一定是满足条件的(只要a<10^9
)。这是因为:
a^1
只是改变了a
的最低位,所以c=a^1
必然在合法范围内- 验证:
b^c = 1^(a^1) = a
因此,我们甚至可以进一步简化代码,直接输出1
和a^1
作为答案,无需循环查找,将时间复杂度从O(n)
降低到O(1)
。
示例分析
以示例中的第一组数据为例:a=1
- 选择
b=2
(二进制为10
) - 计算
c=a^b=1^2=3
(二进制为11
) - 验证:
b^c=2^3=1=a
✓
通过这个示例,我们可以直观地看到异或运算的工作原理,并理解为什么这个算法是正确的。
本题考察了位运算的基础知识,尤其是异或运算的性质。虽然题目看似复杂,但利用异或的特性,我们可以快速找到满足条件的解。这也是为什么位运算在算法竞赛和日常编程中如此重要和实用!