HDU 5661 Claris and XOR 贪心

时间:2023-03-09 21:05:09
HDU 5661 Claris and XOR 贪心

题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5661

bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=686&pid=1002

题解:

考虑从高位到低位贪心,对于每一位,

(1)、如果x,y只有唯一的取法,那么只能这么取;否则贪心地必须使答案的这一位等于1。

(2)、如果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)。此时不必继续考虑后面的位。

(3)、如果x,y在这一位并不是0,1都能取,那么由于要使得答案的这一位等于1,也只有唯一的取法。

至此,这一位考虑完毕,然后根据选取的方案,修正一下x和y的范围(只有第(3)种情况要考虑调整x,y范围,比如说如果在第i位,x可以选0,也可以选1,则x选0后b中比i小的位数会变成全1,如果x选1,则a中比i小的位数会变全零),然后对后一位继续这样处理即可。

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL; const LL one=; int n; int main(){
int tc;
scanf("%d",&tc);
while(tc--){
LL a,b,c,d;
int tag1,tag2,tag3,tag4;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
LL ans=;
for(int i=;i>=;i--){
tag1=tag2=tag3=tag4=;
if(a&(one<<i)) tag1=;
if(b&(one<<i)) tag2=;
if(c&(one<<i)) tag3=;
if(d&(one<<i)) tag4=;
// if(i<=3) printf("(%d,%d,%d,%d)\n",tag1,tag2,tag3,tag4);
if((tag1^tag2)&&(tag3^tag4)){
ans|=((one<<(i+))-);
break;
}else if(!(tag1^tag2)&&!(tag3^tag4)){
if(tag1^tag3){
ans|=(one<<i);
}
}else if(tag1^tag2){
if(tag1^tag3){
b=(one<<i)-;
}else{
a=;
}
ans|=(one<<i);
}else if(tag3^tag4){
if(tag3^tag1){
d=(one<<i)-;
}else{
c=;
}
ans|=(one<<i);
}
}
printf("%lld\n",ans);
}
return ;
}