CF627A XOR Equation

CF627A XOR Equation

洛谷传送门

题意翻译

题目描述

两个合法的整数 ab 的和为s,它们的按位异或和为x。请计算出所有可能的有序数对(a,b)的个数。

输入格式

输入共一行,包含两个整数s(2<=s<=1012)和x(2<=x<=1012)。

输出格式

输出一个整数,为合法的有序数对的个数。如果不存在合法的数对,则输出0。

样例解释

对于第一个样例,有以下合法的数对:(2,7) (3,6) (6,3) (7,2);

对于第二个样例,有以下合法的数对:(1,2) (2,1)


题解:

首先,异或是不进位的加法。

所以我们的目光就定位在“进位”这个位置。

这时我们发现一个性质:(a+b=(a&b)<<1+(a ext{xor} b))

也就是说,((s-x)>>1)就是((a&b))

这时我们要把两种答案为0的情况拎出来:也就是(s-x)不能被2整除,或者s-x<0。

然后我们开始逐位枚举(a&b)这个数。对于某一位为1的情况,显然a,b的对应位都要得1.那么这种情况,如果给出的x还限制这一位为1(不同)的话,那么就不合法。直接输出0.

对于某一位为0的情况,显然(a,b)有(0,1)(1,0)和(0,0)三种抉择,那么这时如果x限制这一位为0,那只能是(0,0),如果x限制这一位为1,说明有两种可能,需要乘上2.

需要说明的是,翻译有误。只能是正整数,不是它所说的整数。所以最后如果(a&b)=0的话,要减去2.

AC代码:

#include<cstdio>
#define ll long long
using namespace std;
ll s,x,yu,ans;
int main()
{
	scanf("%lld%lld",&s,&x);
	ans=1;
	yu=(s-x);
	if(yu&1||s<x)
	{
		puts("0");
		return 0;
	}
	yu>>=1;
	for(int i=0;i<=60;i++)
	{
		if((yu>>i&1)&&(x>>i&1))
		{
			puts("0");
			return 0;
		}
		if((!(yu>>i&1))&&(x>>i&1))
			ans*=2;
	}
	if(!yu)
		ans-=2;
	printf("%lld
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/14032101.html