AtCoder Grand Contest 015 D - A or...or B Problem 构造

题意

给出b,a,问用区间[b,a]中的数可以通过or运算得到多少个不同的数。
a,b<=2^60

分析

设a和b的最高不同位为d,a从d开始的第二个非零位为k。我们把所有数分成两部分,第一部分是d位上是1。
显然不管选哪几个数进行or运算,d之前的位置都是相同的,所以不妨把d之前的位去掉。
先对每个部分单独考虑。
对于第二部分 [b,2d1] [ b , 2 d − 1 ] ,显然两个数or起来的结果不会小于两个数中较大的那个,所以只用第二部分的数可以得到 [b,2d1] [ b , 2 d − 1 ] 中的数。
对于第一部分 [2d,a] [ 2 d , a ] ,不难发现不管怎么选数,k之前的位置都是一样的。考虑从k位开始的位置,我们既可以选10…0也可以选00…0,然后k后面的位置就可以任意取了。所以可以得到 [2d,2d+2k+11] [ 2 d , 2 d + 2 k + 1 − 1 ] 中的数。
如果两部分都要用的话,d位上一定是1,且d位后的最小是b,最大是 2d1 2 d − 1 ,所以能得到 [2d+b,2d+11] [ 2 d + b , 2 d + 1 − 1 ] 中的数。
三个区间取并集就好了。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;

LL a,b,bin[65];

int main()
{
    scanf("%lld%lld",&b,&a);
    if (a==b) {puts("1");return 0;}
    bin[0]=1;
    for (int i=1;i<=60;i++) bin[i]=bin[i-1]*2;
    int d=60;
    while ((a&bin[d])==(b&bin[d])) d--;
    a&=bin[d+1]-1;b&=bin[d+1]-1;
    int k=d-1;
    while (k>=0&&!(a&bin[k])) k--;
    LL l1=b,r1=bin[d]+bin[k+1]-1,l2=bin[d]+b,r2=bin[d+1]-1;
    l2=max(l2,r1+1);
    printf("%lld",r1-l1+1+max((LL)0,r2-l2+1));
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值