A. XORwice(思维)Codeforces Round #676 (Div. 2)

原题链接: https://codeforces.com/contest/1421/problem/A

在这里插入图片描述
测试样例

input
6
6 12
4 9
59 832
28 14
4925 2912
1 1
output
10
13
891
18
6237
0

Note

For the first test case Sana can choose x=4 and the value will be ( 6 ⊕ 4 ) + ( 12 ⊕ 4 ) = 2 + 8 = 10 (6⊕4) + (12⊕4) = 2+8 = 10 (64)+(124)=2+8=10. It can be shown that this is the smallest possible value.

题意: 给出两个数 a a a b b b,要求你选择一个数 x x x,使得 ( a ⊕ x ) + ( b ⊕ x ) (a⊕x) + (b⊕x) (ax)+(bx)的结果最大。(⊕代表异或操作)

解题思路: 我们思考一下,进行异或操作即是位相同的取 0 0 0,位不同的取 1 1 1,那么我们希望尽量让位相同使得进行操作后数会变小,那么该如何选择呢?综合两个数 a a a b b b,假设第 i i i位上 a a a为1, b b b 0 0 0,那么不管你此时 x x x的第 i i i为取什么值都不会改变大小,只有当他们都为 1 1 1时取 1 1 1。这样经过异或操作后此位上变为 0 0 0,则和会变小。 故我们要做的就是构建一个 x x x,使得它能最优化上述操作。我们有两种方法可以解决。第一种方法是我比赛的时候解决的,即取出两个数的 2 2 2进制的位数,然后对比得到 x x x。而第二种方法特别牛,是参考 c f cf cf大佬的,即这个结果最优其实就是 a ⊕ b a⊕b ab。为什么呢?因为这个就是位数相同的取0,不同的取 1 1 1。最后相加也确实是不同的位数其中一个是0,一个是1,那么相加为1。而直接进行异或操作即可达到这个效果。相当于是一个公式推导吧,牛。

AC代码1

/*
*邮箱:[email protected]
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h>	//POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

int t,n;
int a,b;
void solve(){
    
    
	vector<int> a1;
	vector<int> b1;
	int temp1=a,temp2=b;
	while(a){
    
    
		a1.push_back(1&a);
		a=a>>1;
	}
	while(b){
    
    
		b1.push_back(1&b);
		b=b>>1;
	}
	int len=min(a1.size(),b1.size());
	int ans=0;
	rep(i,0,len-1){
    
    
		ans+=a1[i]*pow(2,i);
	}
	cout<<(ans^temp1)+(ans^temp2)<<endl;
}
int main(){
    
    
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>a>>b;
			solve();
		}
	}
	return 0;
}

AC代码2

/*
*邮箱:[email protected]
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h>	//POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

int t,n;
int a,b;
int main(){
    
    
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>t){
    
    
		while(t--){
    
    
			cin>>a>>b;
			cout<<(a^b)<<endl;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hzf0701/article/details/109153612