给定一个区间 [ A , B ] [A,B] [A,B] ,从中选出两个数 x x x 和 y y y , x x x 可以等于 y y y ,问 x x x 或 y y y 的结果可以得到多少个不同的数。
如果 A = B A=B A=B,那么答案就是 1 1 1 。特判即可。
对于 [ A , B ] [A,B] [A,B] 中的数, A A A 和 B B B 的二进制表示前缀中相同的部分或运算后的值必然是确定的,所以这部分可以不用考虑了。
举个例子: A = 13 = 110 0 2 , B = 15 = 111 1 2 A=13=1100_2,B=15=1111_2 A=13=11002,B=15=11112,两者二进制都是以 11 11 11 开头的,这部分就是确定的,故这部分可以不用考虑了。
可以将其重新设置为 A = 0 0 2 , B = 1 1 2 A=00_2,B=11_2 A=002,B=112。
B > A B>A B>A ,故两者从高位到低位的第一个不同的二进制数位 k k k, k k k 必然是最高位。
那么我们可以把可选择的数 x x x 和 y y y 分为三部分,其中 x ≥ y x\geq y x≥y
对于
x
k
=
0
,
y
k
=
0
x_k=0,y_k=0
xk=0,yk=0,由于取值最小值为
A
A
A ,取值最大值为
2
k
−
1
2^k-1
2k−1 ,故或运算的值必然在这个范围内。
具体构造出值
v
∈
[
A
,
2
k
−
1
]
v\in[A, 2^k-1]
v∈[A,2k−1],令
x
=
y
=
v
x=y=v
x=y=v 即可。
对于
x
k
=
1
,
y
k
=
0
x_k=1,y_k=0
xk=1,yk=0,第
k
k
k 位或运算结果为
1
1
1 ,那么只需要考虑低
k
−
1
k-1
k−1 位。因为
y
≥
A
y\geq A
y≥A ,所以或运算的结果必然
≥
A
\geq A
≥A ,但是低
k
−
1
k-1
k−1 位至多是全部为
1
1
1 ,即
2
k
−
1
2^k-1
2k−1 。
具体构造出值
v
∈
[
2
k
+
A
,
2
k
+
1
−
1
]
v\in[2^k+A, 2^{k+1}-1]
v∈[2k+A,2k+1−1],令
x
=
2
k
,
y
=
v
−
2
k
x=2^k,y=v-2^k
x=2k,y=v−2k 即可。
对于
x
k
=
1
,
y
k
=
1
x_k=1,y_k=1
xk=1,yk=1,如果
B
=
2
k
B=2^k
B=2k ,那么只能选择一个数。
否则
B
>
2
k
B>2^k
B>2k ,
s
s
s 为从高位到低位第二个为
1
1
1 的二进制位。
对于
b
i
t
∈
(
s
,
k
)
bit\in(s,k)
bit∈(s,k) 的二进制位
b
i
t
bit
bit ,这些必然不可能为
1
1
1 。
那么
v
k
,
v
k
−
1
,
⋯
,
v
s
+
1
v_k,v_{k-1},\cdots,v_{s+1}
vk,vk−1,⋯,vs+1 这些二进制位都已确定。那么可以构造出
[
2
k
,
2
k
+
2
s
+
1
−
1
]
[2^k, 2^k+2^{s+1}-1]
[2k,2k+2s+1−1] 。
具体构造出值
v
∈
[
2
k
,
2
k
+
2
s
+
1
−
1
]
v\in[2^k, 2^{k}+2^{s+1}-1]
v∈[2k,2k+2s+1−1]
当然,这里的 x k = 1 , y k = 0 x_k=1,y_k=0 xk=1,yk=0 和 x k = 1 , y k = 1 x_k=1,y_k=1 xk=1,yk=1 的取值区间可能会有交集。
因为 2 k < 2 k + A 2^k<2^k+A 2k<2k+A ,所以必然是 2 k + 2 s + 1 − 1 ≥ 2 k + A 2^{k}+2^{s+1}-1\geq 2^k+A 2k+2s+1−1≥2k+A ,即 2 s + 1 − 1 ≥ A 2^{s+1}-1\geq A 2s+1−1≥A ,即 2 s + 1 > A 2^{s+1}>A 2s+1>A ,此时 A A A 的二进制为 1 1 1 的最高位小于等于 B B B 的二进制为 1 1 1 的次高位。
时间复杂度: O ( log max ( A , B ) ) O(\log \max(A,B)) O(logmax(A,B)) ,至多 60 60 60
#include
using namespace std;
typedef long long ll;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
ll A, B;
cin >> A >> B;
if (A == B) {
cout << "1\n";
return 0;
}
vector<int> vecA(60), vecB(60);
for (int i = 0; i < 60; ++i) {
vecA[i] = A % 2;
vecB[i] = B % 2;
A /= 2;
B /= 2;
}
while (!vecA.empty() && vecA.back() == vecB.back()) {
vecA.pop_back();
vecB.pop_back();
}
int n = int(vecA.size());
reverse(vecA.begin(), vecA.end());
reverse(vecB.begin(), vecB.end());
int s = -1;
for (int i = 1; i < vecB.size(); ++i) {
if (vecB[i] == 1) {
s = n - 1 - i;
break;
}
}
ll ans = 0;
A = 0;
for (int i = 0; i < vecA.size(); ++i) A = A * 2 + vecA[i];
ll R = (1ll << (n - 1)) + (1ll << (s + 1)) - 1;
ll L = A;
if (R >= (1ll << (n - 1)) + A) {
R = (1ll << n) - 1;
ans = R - L + 1;
} else {
ans = R - L + 1;
ans += (1ll << (n - 1)) - 1 - A + 1;
}
cout << ans << "\n";
return 0;
}