原题链接
给定一个区间 [ 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;
}