[AtCoderContest015D]A or...or B Problem

试题描述

Nukes has an integer that can be represented as the bitwise OR of one or more integers between \(A\) and \(B\) (inclusive). How many possible candidates of the value of Nukes's integer there are?

求 \(A\) 和 \(B\) 之间选若干个数按位或起来有多少种可能的值。

输入

The input is given from Standard Input in the following format:

A
B

输出

Print the number of possible candidates of the value of Nukes's integer.

输入示例1

7
9

输出示例1

4

输入示例2

65
98

输出示例2

63

输入示例3

271828182845904523
314159265358979323

输出示例3

68833183630578410

数据规模及约定

\(1 \le A \le B < 2^{60}\)

\(A\) and \(B\) are integers.

题解

题目地址

首先,\([A, B]\) 范围内的数肯定是能表示出来的。然后我们考虑一下它能表示出的最小的数和最大的数。

最小的数肯定是 \(A\)。然后我们考虑将 \(A\) 和 \(B\) 分解成二进制的形式,设它们前 \(k\) 位的二进制都相同,那么第 \(k+1\) 位上 \(B\) 的肯定是 \(1\),\(A\) 的肯定是 \(0\),那么最大值就很好考虑了。我们现在用 \((XXX...)_2\) 表示前 \(k\) 位相同的二进制,那么 \([A, B]\) 区间可以被拆成 \([A, (XXX...011...)_2]\) 和 \([(XXX...100...)_2, B]\),下面的数字应该会直观一些:

XXX...0****** = A
XXX...0111111 = C
XXX...1000000 = D
XXX...1001--- = B

上面的例子就假设后面只有 \(7\) 位,其中 * 表示 \(A\) 的后几位,- 表示 \(B\) 的后几位。

那么显然我们可以用 \(C\texttt{ }or\texttt{ }D\) 得到最大值 \(XXX...1111111\)。

除此之外,区间 \([A, C]\) 中每个数都可以和 \(D\) 进行按位或运算得到下面这个范围的所有数:

XXX...1****** = E
XXX...1111111 = F

注意到我们用 \([D, B]\) 内部的所有数按位或起来可以得到这个范围的所有数:

XXX...1000000 = D
XXX...1001111 = G

然后我们发现除此之外,再无其他可以搞出来的数了。考虑只用 \([A, G]\) 中的数,组出来的是 \([A, G]\) 或 \([E, F]\) 的数;只用 \([E, F]\) 的数,只能组出来 \([E, F]\) 中的数;两个区间都用只能组出来 \([E, F]\) 中的数,因为数是越或越大的。

所以最后答案就是 \([A, G] \bigcup [E, F]\) 中的所有数了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define LL long long LL read() {
LL x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} int main() {
LL l = read(), orgl = l, r = read(), orgr = r, tr = r, ans; for(int i = 59; i >= 0; i--)
if((l ^ r) >> i & 1) {
l |= 1ll << i;
int tmp = i;
for(tmp--; tmp >= 0; tmp--) tr |= 1ll << tmp;
for(i--; i >= 0 && !(r >> i & 1); i--) ;
for(i; i >= 0; i--) r |= 1ll << i;
break;
}
if(r >= l) return printf("%lld\n", tr - orgl + 1), 0;
ans = r - orgl + 1 + tr - l + 1; printf("%lld\n", ans); return 0;
}

最新文章

  1. 我常用的Vi命令
  2. hdu 1041 (OO approach, private constructor to prevent instantiation, sprintf) 分类: hdoj 2015-06-17 15:57 25人阅读 评论(0) 收藏
  3. 学习Swift -- 构造器(上)
  4. Image Builder, 快速固件生成器
  5. Semaphore (通常用于限制可以访问某些资源(物理或逻辑的)的线程数目)
  6. memcached vs MySQL Memory engine table 速度比较_XMPP Jabber即时通讯开发实践_百度空间
  7. ssh密钥登录及远程执行命令
  8. 解决CentOS7安装Tomcat不能被外部访问的问题
  9. MySQL之字符集
  10. 读zepto源码之工具函数
  11. python学习笔记八(集合)
  12. Jenkins-job之间依赖关系配置
  13. day50 django第一天 自定义框架
  14. Linux 小知识翻译 - 「桌面环境」
  15. poj--2299(树状数组+离散化)
  16. 各大引擎矩阵的矩阵存储方式 ----行矩阵 or 列矩阵
  17. Bootstrap学习笔记-响应式布局原理
  18. cdoj第13th校赛初赛F - Fabricate equation
  19. Ajax中文传参出现乱码
  20. 11. Container With Most Water 装水最多的容器

热门文章

  1. Python3之偏函数
  2. 【转】Intellij IDEA 提交代码到远程GitHub仓库
  3. js中读取解析json数据
  4. 谈谈TCP的四次挥手
  5. php常见验证
  6. ios sinaweibo 客户端(二)
  7. 51nod——2502最多分成多少块
  8. 洛谷 P1593 因子和
  9. PHP获取文件夹内所有文件包括子目录文件的名称或路径
  10. Anaconda安装和环境的搭建