B 撕书II-3 SRM 09

背景&&描述

琉璃手头有一黑一白两本魔法书,一本是《缟玛瑙的不在证明》,另一本是《白色相簿1.5》
    传说同时打开这两本书会有奇怪的事情发生。
    琉璃打开一看,果然非常奇怪:两本书上都各自写着一个正整数(可能他买到盗版了),分别是a和b。
    试图撕书的汀想借过来看看,但琉璃只告诉了他这俩数加起来的值x和异或起来的值y。
    汀发现有很多种(a,b)满足琉璃告诉他的信息...你能帮他算出来有多少种吗?

输入格式

两个用空格隔开的整数x和y。

输出格式

一个整数,表示有多少种情况。

样例输入

9 5

样例输出

4

数据范围与约定

  • 对于100%的数据:汕头市队赛 SRM 09 B  撕书-LMLPHP

样例解释

四种分别为(2,7),(7,2),(3,6),(6,3)

——————————————————————————————

这道题是关于异或性质的题 以前没涉及过写得很困难 少推了一点性质QAQ过于蒟蒻啊

cyc大爷原话:

  异或是不进位加法,知道这点其它就很容易了
   异或最重要的性质之一就是这个
  不进位是针对每一位的
  这些1可以通过(x-y)>>1体现出来

这样我们找到所有的进位位置

如果这一位(二进制位)是要进位的那么y在这一位的值一定是0 因为1^1=0

这样筛完解是0的情况后

我们统计y是1的位数(仍为二进制位) k

答案就是2^k辣 不过如果x==y要-2 因为题目要求是正整数 而这种情况下存在0和x的情况

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
LL read(){
LL ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
LL x,y,c,ans=;
int main()
{
x=read(); y=read();
c=x-y;
if(c&||x<y){printf("");return ;}
c>>=;
for(int i=;(1LL<<i)<=c;i++) if(c&(1LL<<i)&&y&(1LL<<i)){printf("0\n"); return ;}
for(int i=;(1LL<<i)<=y;i++) if((1LL<<i)&y) ans*=;
if(x==y) ans-=;
printf("%lld\n",ans);
return ;
}
05-27 09:42