计数范围 [L, R] 中只有三个设置位的数字
给定一个N对数组arr[] ,其中每个数组元素表示{L, R} 形式的查询,任务是找到[L, R]范围内的数字的计数,只有 3 个集合位对于每个查询{L, R}。
例子:
Input: arr[] = {{11, 19}, {14, 19}}
Output: 4
2
Explanation:
- Query(11, 19): Numbers in the range [11, 19] having three set bits are {11, 13, 14, 19}.
- Query(14, 19): Numbers in the range [14, 19] having three set bits are {14, 19}.
Input: arr[] = {{1, 10}, {6, 12}}
Output: 1
2
Explanation:
- Query(1, 10): Numbers in the range [1, 10] having three set bits are {7}.
- Query(6, 12): Numbers in the range [6, 12] having three set bits are {7, 12}.
方法:解决这个问题的思路是先做一个预计算,把所有只有3位的数字存储在[1, 10 18 ]范围内,然后用二分查找找到L的下界和上界的位置的R并返回答案,因为存在差异。请按照以下步骤解决给定的问题:
- 初始化一个向量,比如V ,以存储范围[1, 10 18 ]中的所有数字,并且只设置了三位。
- 使用变量i, j迭代由关系[0, 63]×[0, 63]×[0, 63]形成的每个三元组,和k并执行以下步骤:
- 如果i、j和k不同,则使用 第i位、第j 位和第k位设置,如果数量小于10 18 ,推动向量V中的数字。
- 按升序对向量 V 进行排序。
- 使用变量i遍历数组arr[],并执行以下步骤:
- 将查询的边界分别存储在变量中,例如L和R 。
- 求向量V中L的下界和R的上界的位置。
- 打印R的上限位置和L的下限位置之间的差,作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to precompute
void precompute(vector& v)
{
// Iterate over the range [0, 64]
for (long long i = 0; i < 64; i++) {
// Iterate over the range [0, 64]
for (long long j = i + 1; j < 64; j++) {
// Iterate over the range [0, 64]
for (long long k = j + 1; k < 64; k++) {
// Stores the number with set bits
// i, j, and k
long long int x
= (1LL << i) | (1LL << j) | (1LL << k);
// Check if the number is less
// than 1e18
if (x <= 1e18 && x > 0)
v.push_back(x);
}
}
}
// Sort the computed vector
sort(v.begin(), v.end());
}
// Function to count number in the range
// [l, r] having three set bits
long long query(long long l, long long r,
vector& v)
{
// Find the lowerbound of l in v
auto X = lower_bound(v.begin(), v.end(), l);
// Find the upperbound of l in v
auto Y = upper_bound(v.begin(), v.end(), r);
// Return the difference
// in their positions
return (Y - X);
}
void PerformQuery(vector > arr,
int N)
{
// Stores all the numbers in the range
// [1, 1e18] having three set bits
vector V;
// Function call to perform the
// precomputation
precompute(V);
// Iterate through each query
for (auto it : arr) {
long long L = it.first;
long long R = it.second;
// Print the answer
cout << query(L, R, V) << "\n";
}
}
// Driver Code
int main()
{
// Input
vector > arr
= { { 11, 19 }, { 14, 19 } };
int N = arr.size();
// Function call
PerformQuery(arr, N);
return 0;
}
输出
4
2
时间复杂度: O(N*log(63 3 )+ 63 3 )
辅助空间: O(63 3 )