CF627A XOR Equation
题意翻译
题目描述
两个合法的整数 a 和 b 的和为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;
}