hdu 5661異或
1969 ワード
2つの区間、(a,b)と(c,d)、データ範囲はlong longであり、この2つの区間の中でそれぞれ1つの数字を選択して異を求めるか、最大の異または値を求める.
公式の問題解:
高位から低位への貪欲さを考えると、一人一人に対して、x、yが唯一の取り方しかないなら、そうするしかない.そうでなければ、貪欲に答えを1にしなければならない.x,yがいずれも0,1であれば,これを右から左に数えてlen番目のビットとする.x,yで取れる値は必ず連続するセグメントであるため,x,yの後lenビットはいずれも0111をとることができる.1(len-1個1)と1000...0(len-1個0)(そうでなければ右から左に数えてもlen位が0,1を取ることはできない).つまり、後len位の寄与は必ず可能な上界111...1(len個1)に達する.この場合、後の位を考慮し続ける必要はない.
x,yがこの1位で0,1でも取れるわけではない場合、答えの1位を1に等しくするには、唯一の取り方しかないからです.
これで、この方は考え終わって、選択した案に基づいて、xとyの範囲を修正して、次の方にすればいいです.
公式の問題解:
高位から低位への貪欲さを考えると、一人一人に対して、x、yが唯一の取り方しかないなら、そうするしかない.そうでなければ、貪欲に答えを1にしなければならない.x,yがいずれも0,1であれば,これを右から左に数えてlen番目のビットとする.x,yで取れる値は必ず連続するセグメントであるため,x,yの後lenビットはいずれも0111をとることができる.1(len-1個1)と1000...0(len-1個0)(そうでなければ右から左に数えてもlen位が0,1を取ることはできない).つまり、後len位の寄与は必ず可能な上界111...1(len個1)に達する.この場合、後の位を考慮し続ける必要はない.
x,yがこの1位で0,1でも取れるわけではない場合、答えの1位を1に等しくするには、唯一の取り方しかないからです.
これで、この方は考え終わって、選択した案に基づいて、xとyの範囲を修正して、次の方にすればいいです.
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
using namespace std ;
// x i 1, y i 0, y i-1 11...11
// x i 0, y i 1, y i-1 00...00
// , x,y 。
int main()
{
int t;
long long a , b , c , d ;
long long aa , bb , cc , dd ;
scanf("%d",&t);
while(t--)
{
scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d);
long long ans = 0 ;
for(long long cur = 1LL << 61 ; cur > 0 ; cur >>= 1)
{
aa=a&cur; bb=b&cur;
cc=c&cur; dd=d&cur;
if(aa==bb)
{ // x 0 1
if(cc==dd)
{ // y 0 1
ans|=aa^cc;
}
else
{ // y 0 1
ans|=cur;//ans 1
if(aa==0)
{ // x 0, y 1
c&=cur;//y 00...00
}
else
{ // x 1, y 0
d|=cur-1;//y 11...11
}
}
}
else
{ // x 0 1
ans|=cur; //ans 1
if(cc==dd)
{ // y 0 1
if(cc==0)
{ // y 0, x 1
a&=cur;
}
else
{ // y 1, x 0
b|=cur-1;
}
}
else
{ // y 0 1 , , ans 1
ans|=cur-1;
break;
}
}
}
printf("%I64d
",ans) ;
}
return 0;
}