题意没看清以为d>b…..结果比赛时没做出来
从高位往地位递推,递推时贪心选择最优解。
结论 1:递推到x位时,b此位的数必定>=a此位的数。d此位的数必定>=c此位的数。
证明:因为递推的过程不断刷新上下限,a和b的上一位一定相同,c和d的上一位一定相同,又因为b>=a,d>=c,所以可证
注意取模1LL!!!
#include<cstdio>
#define LL long long
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL a,b,c,d,aa,bb,cc,dd,ans = 0;
scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d);
for(int i=62;i>=0;i--)
{
aa = a&(1LL<<i);
bb = b&(1LL<<i);
cc = c&(1LL<<i);
dd = d&(1LL<<i);
if(!aa&&bb&&!cc&&dd)
{
ans+=(1LL<<(i+1))-1;//10000 和 01111 以后全为1 跳出
break;
}
else if(dd&&!aa)//结论1 取两个区间此位的最大值和最小值
{
ans+=(1LL<<i);
if(b&(1LL<<i))b = (1LL<<i)-1;
if(!(c&(1LL<<i)))c = (1LL<<i);
}
else if(bb&&!cc) //同上
{
ans+=(1LL<<i);
if(d&(1LL<<i))d = (1LL<<i)-1;
if(!(a&(1LL<<i)))a = (1LL<<i);
}
}
printf("%I64d\n",ans);
}
}
第一发乱搞版。。。
#include<cstdio>
#define ll long long
long long t,a,b,c,d;
int main()
{
scanf("%I64d",&t);
while(t--)
{
scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d);
long long d1 = d,n = 0,ans = 0;
for(ll i=62;i>=0;i--)
{
if((d&(1LL<<i))!=0&&(c&(1LL<<i))==0)
{
if((b&(1LL<<i))!=0&&(a&(1LL<<i))==0)
{
ans+=(1LL<<i);
ans+=(1LL<<i)-1;
break;
}
else if((b&(1LL<<i))!=0&&(a&(1LL<<i))!=0)
{
ans+=(1LL<<i);
for(ll j=0;j<=i;j++)
if(d&(1LL<<j))d-=(1LL<<j);
d+=((1LL<<i)-1);
}
else if((b&(1LL<<i))==0&&(a&(1LL<<i))==0)
{
ans+=(1LL<<i);
for(ll j=0;j<=i;j++)
if(c&(1LL<<j))c-=(1LL<<j);
c+=(1LL<<i);
}
}
else if((d&(1LL<<i))!=0&&(c&(1LL<<i))!=0)
{
if((b&(1LL<<i))!=0&&(a&(1LL<<i))==0)
{
ans+=(1LL<<i);
for(ll j=0;j<=i;j++)
if(b&(1LL<<j))b-=(1LL<<j);
b+=((1LL<<i)-1);
}
else if((b&(1LL<<i))!=0&&(a&(1LL<<i))!=0)
{
;
}
else if((b&(1LL<<i))==0&&(a&(1LL<<i))==0)
{
ans+=(1LL<<i);
}
}
else if((d&(1LL<<i))==0&&(c&(1LL<<i))==0)
{
if((b&(1LL<<i))!=0&&(a&(1LL<<i))==0)
{
ans+=(1LL<<i);
for(ll j=0;j<=i;j++)
if(a&(1LL<<j))a-=(1LL<<j);
a+=(1LL<<i);
}
else if((b&(1LL<<i))!=0&&(a&(1LL<<i))!=0)
{
ans+=(1LL<<i);
}
else if((b&(1LL<<i))==0&&(a&(1LL<<i))==0)
{
}
}
}
printf("%I64d\n",ans);
}
}