蚂蚁的难题(一)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
2
-
描述
-
小蚂蚁童鞋最近迷上了位运算,他感觉位运算非常神奇。不过他最近遇到了一个难题:
给定一个区间[a,b],在区间里寻找两个数x和y,使得x异或y最大。来,帮帮他吧!
-
输入
-
有多组测试数据(以EOF结尾)。
每组数据输入两个数a,b.(0<=a<b<2^63)
输出
- 输出a到b之间,异或最大的值。 样例输入
-
1 2 8 9
样例输出
-
3 1
来源
解题思路:求一个区间[a,b]中任意两个数异或的最大值:
先做a^b得到一个数,该数二进制的第一个1(位置为q)一定产生于a的1和b的0做异或(因为a>b),所以q以上的位置a,b都是1,无法调动。但q以下的位置的0无论产生于a的1,b的1或是a的0,b的0,都可以对应调小a或者调大b来使得最终异或的结果为1111111……i.e. 2^cnt-1。
错误思路:暴力求出任意两个数的二进制,再求出异或值,枚举找出最大的。。。。。超时........当时对异或完全没有概念,没思路啊,,,,
错误代码:
#include<bits/stdc++.h> using namespace std; int a[100]= {0},b[100]= {0},ans,k1,k2,sum; long long pp(long long aa,long long bb) { k1=0; k2=0; sum=0; while(aa) { a[k1++]=aa%2; aa/=2; } while(bb) { b[k2++]=bb%2; bb/=2; } ans=k1>k2?k1:k2; for(int i=0; i<ans; i++) { if(a[i]==b[i]) sum+=0; else sum+=pow(2,i); } return sum; } int main() { long long x,y,i,j,max; while(~scanf("%lld%lld",&x,&y)) { max=0; for(i=x; i<=y; i++) for(j=i+1; j<=y; j++) { if(pp(i,j)>max) max=pp(i,j); } printf("%lld\n",max); } return 0; }
正解:
#include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> using namespace std; int main() { long long a,b,x,ans,sum; while(~scanf("%lld%lld",&a,&b)) { ans=0; x=a^b;//求a,b的异或值 while(x) { ans++;//找出二进制中一的个数 x/=2; } sum=pow(2,ans)-1; printf("%lld\n",sum); } return 0; }
-
有多组测试数据(以EOF结尾)。