题目描述
给出一个数字n,表示有n组输入用例子,每一组输入给出三个正整数a、b、c,可以对a和b进行位翻转操作,每一次操作可以翻转a或b的某一位,比如0010操作一次可以得到0011,求使得 a ∣ b = c a|b=c a∣b=c 成立的最小操作次数。 ∣ | ∣ 表示按位或操作。
输入输出示例
输入:
1
2,6,5
输出:
3
解释:
a = 0010,b = 0110,c = 0101
对最低位进行一次翻转操作,对a和b第二位各进行一次翻转操作,一共三次。
解题思路
可以按位读取a、b、c,若
a
i
∣
b
i
=
c
i
a_i|b_i = c_i
ai∣bi=ci,本位不需要操作,否则分类讨论,若
c
i
=
0
c_i=0
ci=0,说明
a
i
a_i
ai 和
b
i
b_i
bi 至少有一位是1,要进行1到2次操作,取决于
a
i
a_i
ai 是否等于
b
i
b_i
bi;当
c
i
=
1
c_i = 1
ci=1 时,说明说明
a
i
a_i
ai 和
b
i
b_i
bi 都为0,所以进行一次操作即可。
在编写代码时,可以通过 a&1
来取a的最后一位,任何数字和1按位与都能得到最后一位。
代码
#inlcude <iostream>
using namespace std;
int main(){
int n;
cin>>n;
while(n--){
int a,b,c;
cin>>a>>b>>c;
int res = 0;
// 只要a,b,c有任何一个还不为0,就要继续操作
while(a>0 || b>0 ||c>0) {
// 任何数字和1按位与操作就可以得到最后一位
int alast = a & 1;
int blast = b & 1;
int clast = c & 1;
if((alast | blast) != clast){
if(clast == 1) res += 1;
else res += alast==blast?2:1;
}
// 三个数字各删去最后一位,高位降低一位
a = a >> 1;
b = b >> 1;
c = c >> 1;
}
cout<<res<<endl;
}
}