B 撕书II-3 SRM 09
背景&&描述
琉璃手头有一黑一白两本魔法书,一本是《缟玛瑙的不在证明》,另一本是《白色相簿1.5》
传说同时打开这两本书会有奇怪的事情发生。
琉璃打开一看,果然非常奇怪:两本书上都各自写着一个正整数(可能他买到盗版了),分别是a和b。
试图撕书的汀想借过来看看,但琉璃只告诉了他这俩数加起来的值x和异或起来的值y。
汀发现有很多种(a,b)满足琉璃告诉他的信息...你能帮他算出来有多少种吗?
输入格式
两个用空格隔开的整数x和y。
输出格式
一个整数,表示有多少种情况。
样例输入
9 5
样例输出
4
数据范围与约定
- 对于100%的数据:
样例解释
四种分别为(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 "); return 0;} for(int i=0;(1LL<<i)<=y;i++) if((1LL<<i)&y) ans*=2; if(x==y) ans-=2; printf("%lld ",ans); return 0; }