Claris and XOR
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 874 Accepted Submission(s): 402
Problem Description
Claris loves bitwise operations very much, especially XOR, because it has many beautiful features. He gets four positive integers a,b,c,d that satisfies a≤b and c≤d . He wants to choose two integers x,y that satisfies a≤x≤b and c≤y≤d , and maximize the value of x XOR y . But he doesn't know how to do it, so please tell him the maximum value of x XOR y .
Input
The first line contains an integer
T(1≤T≤10,000)
——The number of the test cases.
For each test case, the only line contains four integers
a,b,c,d(1≤a,b,c,d≤1018)
. Between each two adjacent integers there is a white space separated.
Output
For each test case, the only line contains a integer that is the maximum value of x XOR y .
Sample Input
2 1 2 3 4 5 7 13 15
Sample Output
6 11HintIn the first test case, when and only when $x=2,y=4$, the value of $x~XOR~y$ is the maximum. In the second test case, when and only when $x=5,y=14$ or $x=6,y=13$, the value of $x~XOR~y$ is the maximum.
Source
现在发现了,一般和异或求最值有关的题目都是贪心。这题,还有16年CCPC Final的题等。
首先,既然是贪心,我们就是得保证,在二进制下,从高到低,每一位都尽量的取1。于是,我们可以根据两个范围分情况讨论。
对于第i位,如果两对端点的相应位都不一样,即x和y的第i位都是既可以取1也可以取0,那么后面的位就可以不用考虑了,直接全部取1即可。至于为什么,就是说如果x取了下界确定的0,那么对于后面的所有位,相当于可以不用考虑上界了,可以全部取1;而对应y取就要取上界确定的1,这样的话,对于后面所有位,不用考虑下界限制,可以全部取0;如此一来全部0和全部1配对,就是可以保证后面最大可以是全部取1。反之同理。
然后如果x和y都是只能取0和1当中一个的话,在判断唯一取值是否相同,如果不同,那么说明这一位可以取到1,否则就只能取到0。
最后是x和y情况不同的时候,即x和y中一个可以取0或1,另一个只能取其中一个。这是我们也是讨论处理。对于有两种选择的数字,如果选取了上界,那么后面就可以不用管下界的限制,直接把下界变为0;如果选取了上界,那么后面可以不用馆上界的限制,直接把上界变为全是1。这个具体道理的话与第一种情况类似。改变了界限之后,不要忘了把答案的这一位变为1。
如此一位一位的确定就能够组合出最后的最大值,时间复杂度O(logN)。具体见代码::
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int main()
{
int T,tt=0;
scanf("%d",&T);
while (T--)
{
bool tag[4]; LL a[4],ans=0;
scanf("%I64d%I64d%I64d%I64d",&a[0],&a[1],&a[2],&a[3]);
for(int i=62;i>=0;i--)
{
for(int j=0;j<4;j++)
tag[j]=(1LL<<i)&a[j]; //tag用来记录对应点对应位的取值情况
if ((tag[0]^tag[1])&&(tag[2]^tag[3]))
{
ans|=(1LL<<(i+1))-1; break; //第一种情况,x和y都是0和1都能取到
} else if (!(tag[0]^tag[1])&&!(tag[2]^tag[3])) //第二种情况,x和y都是取值唯一
{
if (tag[0]^tag[2]) ans|=(1LL<<i);
} else if (tag[0]^tag[1]) //第三种情况,二者之一取值唯一,另外一个取值任意
{
if (tag[0]^tag[2]) a[1]=(1LL<<i)-1;
else a[0]=0;
ans|=(1LL<<i);
} else if (tag[2]^tag[3])
{
if (tag[1]^tag[2]) a[3]=(1LL<<i)-1;
else a[2]=0;
ans|=(1LL<<i);
}
}
printf("%I64d\n",ans);
}
return 0;
}