汕头市队赛 SRM 09 B 撕书

B 撕书II-3 SRM 09

背景&&描述

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

 

输入格式

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

输出格式

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

样例输入

9 5

样例输出

4

数据范围与约定

  • 对于100%的数据:2\leq x\leq 10^{12},0\leq y\leq 10^{12}

样例解释

四种分别为(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=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
LL x,y,c,ans=1;
int main()
{
    x=read(); y=read();
    c=x-y;
    if(c&1||x<y){printf("0");return 0;}
    c>>=1;
    for(int i=0;(1LL<<i)<=c;i++) if(c&(1LL<<i)&&y&(1LL<<i)){printf("0\n"); return 0;}
    for(int i=0;(1LL<<i)<=y;i++) if((1LL<<i)&y) ans*=2;
    if(x==y) ans-=2;
    printf("%lld\n",ans);
    return 0;
}
View Code

 

posted @ 2017-08-03 23:03  友人Aqwq  阅读(180)  评论(0编辑  收藏  举报