题目链接:
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小的位数会变全零),然后对后一位继续这样处理即可。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 typedef long long LL; 6 7 const LL one=1; 8 9 int n; 10 11 int main(){ 12 int tc; 13 scanf("%d",&tc); 14 while(tc--){ 15 LL a,b,c,d; 16 int tag1,tag2,tag3,tag4; 17 scanf("%lld%lld%lld%lld",&a,&b,&c,&d); 18 LL ans=0; 19 for(int i=60;i>=0;i--){ 20 tag1=tag2=tag3=tag4=0; 21 if(a&(one<<i)) tag1=1; 22 if(b&(one<<i)) tag2=1; 23 if(c&(one<<i)) tag3=1; 24 if(d&(one<<i)) tag4=1; 25 // if(i<=3) printf("(%d,%d,%d,%d)\n",tag1,tag2,tag3,tag4); 26 if((tag1^tag2)&&(tag3^tag4)){ 27 ans|=((one<<(i+1))-1); 28 break; 29 }else if(!(tag1^tag2)&&!(tag3^tag4)){ 30 if(tag1^tag3){ 31 ans|=(one<<i); 32 } 33 }else if(tag1^tag2){ 34 if(tag1^tag3){ 35 b=(one<<i)-1; 36 }else{ 37 a=0; 38 } 39 ans|=(one<<i); 40 }else if(tag3^tag4){ 41 if(tag3^tag1){ 42 d=(one<<i)-1; 43 }else{ 44 c=0; 45 } 46 ans|=(one<<i); 47 } 48 } 49 printf("%lld\n",ans); 50 } 51 return 0; 52 }