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《(有两种可能性的位的个数)
因此要控制位移的次数,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); }