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位相与的结果

本文探讨如何利用异或运算与数学公式解决Codeforces竞赛中关于求有序正整数对的问题,具体阐述了如何通过分析a+b与a^b的关系来确定符合条件的整数对数量,并详细解释了处理特殊情况的方法。

2035

被折叠的 条评论
为什么被折叠?



