Problem Description
给你T组测试数据,给你一个闭区间范围a-b,让你求该闭区间的所有数求或,求与。
思路:10^18不会超过1<<60;从b to a 暴力查找各位二进制1 求 或, 查找0 求 与。b to a 一个数一个数的减,肯定会超时,如果比较1<<0为,就减1<<0,如果比较1<<50位,就减1<<50。如果该为是1,肯定会变成0,同理是0,肯定变成1。但是可能由于区间范围没有那么大,减后就直接退出循环了, 所以退出循环后,我们得和a比较。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
scanf("%d", &T);
long long a, b;
int cas = 1;
int ans[70], ans2[70];
long long i, j;
while(T--)
{
scanf("%lld %lld", &a, &b);
memset(ans, 0, sizeof(ans));//用来存 或 结果的二进制
memset(ans2, 0, sizeof(ans2));//用来存 和 结果的二进制
for(i = 0; i < 61; i++)//暴力枚举各个位 求或的和
{
if(((long long)1 << i) > b) break;//如果大于最大的区间,直接退出循环
for(j = b; j >= a; j = j - ((long long) 1 << i))//每次减 1<<i;这样0肯定变成1,1肯定变成0
{
if(((long long)1 << i) & j)//满足代表该位有1
{
ans[i] = 1;
break;
}
}
if(j < a)
{
if(((long long)1 << i) & a)//如果减超过了区间,和a比较,满足该位有1
{
ans[i] = 1;
}
else ans[i] = 0;
}
}
for(i = 0; i < 61; i++)//求与的和
{
if((long long)(1 << i) > b) break;
for(j = b; j >= a; j = j - ((long long) 1 << i))
{
if(!(((long long)1 << i) & j))//有0
{
ans2[i] = 0;
break;
}
}
if(j < a)
{
if(!(((long long)1 << i) & a))
{
ans2[i] = 0;
}
else ans2[i] = 1;
}
}
long long aa = 0, aa2 = 0;
for(i = 0; i < 61; i++)//根据二进制转换十进制
{
aa += ((long long)1 << i) * ans[i];
}
for(i = 0; i < 61; i++)
{
aa2 += ((long long)1 << i) * ans2[i];
}
printf("Case %d: %lld %lld\n", cas++, aa, aa2);//输出
}
}