cf#8VC Venture Cup 2016 - Final Round (Div. 2 Edition)-C - XOR Equation-数学/位运算

http://codeforces.com/contest/635/problem/C

给出 sum,xor

让你求出有多少对 有序正整数对(a,b) 满足 a+b=sum, s^b=xor

有序就是(a,b)(b,a)算两次


得利用到一个公式 :a+b=a^b+(a&b)*2

即:

a+b可分解为a^b[各位相加后该位的结果(不考虑进位)] 加上 (a&b)*2[进位的效果]

把加法过程表现在 每一bit上的 过程,就是这个公式的内容


求到a&b,又知道a^b就好办了

枚举a&b和a^b的每一位,

如果第i位异或的结果为0,表示a,b该位皆为0或1,固定了

如果第i位异或的结果为0,表示a,b该位分别可以为:0和1、1和0两种, 

显然他们相与的结果应该为0,如果为1,表明不存在这样的a,b

如果为0,则表明这一位有两种可能性咯


最后答案就是  1《(有两种可能性的位的个数)


注意 如果给出sum和xor,
1、首先sum-xor 一定应该是偶数,如果是奇数,表示不存在这样的a,b
2、如果a&b==0,表示a,b的方案中存在(0,X)(X,0)两个,要去掉
3、求一个数的每一位的时候,注意如果是负奇数,-1怎么左/右移都是-1(原码全1)

因此要控制位移的次数,63/31


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
 
__int64 xor[65]; 
__int64 and[65]; 

int main()
{
	__int64 s,x;
	scanf("%I64d%I64d",&s,&x);
	//a+b= a^b+(a&b)*2;
	
	s=(s-x);
	if(s%2) {printf("0\n");return 0;}  //(a&b)*2 不可能为奇数,不存在答案
	s/=2;
	__int64 tmps=s;
	int ok=0;
	while(x)	//求a^b的所有位
	{
		xor[++ok]=x&1;
		x>>=1;
		if (ok==63) break;
	}
	ok=0;
	while(s)	//求a&b的所有位
	{
		and[++ok]=s&1;
		s>>=1;
		if (ok==63) break;
	}
	__int64 one=1,ans=0;
	for (int i=1;i<=63;i++)
	{
		if (xor[i]==1&&and[i]==1) {printf("0\n");return 0;} //此情况显然不合法
		if (xor[i]==1)  ans++;		//两种选择
	}	
	one<<=ans;
	if (!tmps)				//如果a&b==0,表示方案中存在(0,x) (x,0)两个,而题目要求是正整数对
	printf("%I64d\n",one-2);
	else
	printf("%I64d\n",one);

} 


如果第i位异或的结果为0,表示a,b该位皆为0或1,固定了
当第i位相与的结果

你可能感兴趣的:(cf#8VC Venture Cup 2016 - Final Round (Div. 2 Edition)-C - XOR Equation-数学/位运算)