http://acm.hdu.edu.cn/showproblem.php?pid=5661
2 1 2 3 4 5 7 13 15
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.
题目大意:给定4个小于等于10^18的数a,b,c,d,又有a<=x<=b,c<=y<=d,求x^y的最大值
昨天只AC了第一题...这样都能涨好多,估计下次div1又得掉好多了
比赛结束后看官方题解没看懂,大脑有点蒙
今天又仔细想了一下,其实从高位开始贪心非常简单,就是有一点绕
对从低位起的第i位考察:
①若x和y第i位取值唯一,则ans与上x,y的第i位的与,x,y的上下限不变
②若x和y第i位有且仅有一个取值唯一,则ans第i为贪心取1,同时变更取值不唯一的数的上下限(例如:若x第i位只能取1,则y第i位贪心取0,同时y的后i-1位上限变为11...11;若x第i位只能取0,则y第i位贪心取1,同时y的后i-1位下限变为00...00)
③若x和y第i为均可以取0和1,则ans后i位均可以贪心得到11...11
(证明:假设x第i位取0,y第i位取1,则x的后i-1位的上限为11...11,y的后i-1位的下限00...00,则x后i-1位可均取11...11,y的后i-1位均取00...00,则ans后i-1位均可得11...11。同理x第i位取1,y第i位取0,ans后i-1位均可得11...11。又ans第i位取1,则ans后i位均可取11...11)
感觉现在屏蔽广告,代码就不高亮了,但是看了几个排名高的博客,屏蔽了没事,是不是无名者就被坑?
#include <cstdio> using namespace std; int main() { int T; long long a,b,c,d,aa,bb,cc,dd,ans; scanf("%d",&T); while(T-->0) { scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d); 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\n",ans); } return 0; }