给定的阵列ARR []由N个整数的,任务是找到按位的AND的(ARR [I] + ARR [j]的)和按位与ARR [I]之和的常用3 [j]的每个对给定数组中的元素(arr [i],arr [j])。由于总和可能非常大,请以模(10 9 + 7)进行打印。
例子:
Input: arr[] = {8, 9}
Output: 0
Explanation: The only pair from the array is (8, 9). Sum of the pair = (8 + 9) = 17. Bitwise AND of the pairs = (8 & 9) = 8. Therefore required Bitwise AND = (17 & 8) = 0.
Input: arr[] = {1, 3, 3}
Output: 2
Explanation:
Pair (1, 3): Required Bitwise AND = (1 + 3) & (1 & 3) = (4 & 1) = 0.
Pair (3, 3): Required Bitwise AND = (3 + 3) & (3 & 3) = (6 & 3) = 2.
Therefore, total sum = 0 + 0 + 2 = 2.
天真的方法:最简单的方法是从给定的数组生成所有可能的对,并检查是否存在满足给定条件的对。如果发现是真的,则算这对。检查所有对之后,打印结果计数。
时间复杂度: O(N 2 )
辅助空间: O(1)
高效的方法:可以基于以下观察来优化上述方法:
- 考虑到一对(X,Y)时,按位与在比特,说第b个是1,那么(X + Y)也必须具有第b个比特为一组位在作出贡献b个比特。
- 仅考虑这样的对的两个数目中的最后b个比特,可以观察到要满足上述条件,第b个比特和第(b + 1)个比特,都必须被设置。
- 因此,从上述步骤可以得出,要满足上述条件,应满足以下条件:
- 因此,该任务减少了找到每个位位置满足上述条件的对的数目,并针对0≤b <31将结果增加cnt * 2 b的值。
请按照以下步骤解决问题:
- 初始化一个变量,例如ans ,以存储结果总和。
- 迭代范围[ 0,30]并执行以下操作:
- 初始化一个向量V ,该向量存储满足上述条件的对。
- 遍历给定数组arr []并将值arr [j] –(arr [j] >>(i + 1))*(1 <<(i + 1))以M为模,插入向量V中,如果(( arr [j] >>(i + 1))&1)为真。
- 将向量V升序排序。
- 遍历向量V并执行以下操作:
- 计算值2 (i + 1) + 2 i – V [j]并将其存储在变量Y中。
- 查找V中大于或等于Y的V中的点计数,并将其存储在变量中,例如cnt,即cnt = V.size()–(lower_bound(V.begin()+ j + 1,V.end (),Y)– V.begin())。
- 将ans更新为ans =(ans + cnt * 2 i )%M 。
- 完成上述步骤后,输出ans的值作为结果。
下面是上述方法的实现:
C++14
// C++ program for the above approach
#include
#define M 1000000007
using namespace std;
// Function to find the sum of Bitwise AND
// of sum of pairs and their Bitwise AND
// from a given array
void findSum(int A[], int N)
{
// Stores the total sum
long long ans = 0;
for (int i = 0; i < 30; i++) {
vector vec;
for (int j = 0; j < N; j++) {
// Check if jth bit is set
if ((A[j] >> i) & 1) {
// Stores the right shifted
// element by(i+1)
long long X = (A[j] >> (i + 1));
// Update the value
// of X
X = X * (1 << (i + 1));
X %= M;
// Push in vector vec
vec.push_back(A[j] - X);
}
}
// Sort the vector in
// ascending order
sort(vec.begin(), vec.end());
// Traverse the vector vec
for (int j = 0; j < vec.size(); j++) {
// Stores the value
// 2^(i+1)- 2^(i)- vec[j]
int Y = (1 << (i + 1))
+ (1 << i)
- vec[j];
// Stores count of numbers
// whose value > Y
int idx = lower_bound(
vec.begin() + j + 1,
vec.end(), Y)
- vec.begin();
// Update the ans
ans += (vec.size() - idx)
* 1ll * (1 << i);
ans %= M;
}
}
// Return the ans
cout << ans % M << endl;
}
// Driver Code
int main()
{
int arr[] = { 1, 3, 3 };
int N = sizeof(arr) / sizeof(arr[0]);
findSum(arr, N);
return 0;
}
Python3
# Python 3 program for the above approach
M = 1000000007
from bisect import bisect_left
# Function to find the sum of Bitwise AND
# of sum of pairs and their Bitwise AND
# from a given array
def findSum(A, N):
# Stores the total sum
ans = 0
for i in range(30):
vec = []
for j in range(N):
# Check if jth bit is set
if ((A[j] >> i) & 1):
# Stores the right shifted
# element by(i+1)
X = (A[j] >> (i + 1))
# Update the value
# of X
X = X * (1 << (i + 1))
X %= M
# Push in vector vec
vec.append(A[j] - X)
# Sort the vector in
# ascending order
vec.sort(reverse=False)
# Traverse the vector vec
for j in range(len(vec)):
# Stores the value
# 2^(i+1)- 2^(i)- vec[j]
Y = (1 << (i + 1)) + (1 << i) - vec[j]
# Stores count of numbers
# whose value > Y
temp = vec[j+1:]
idx = int(bisect_left(temp,Y))
# Update the ans
ans += ((len(vec) - idx) * (1 << i))
ans %= M
ans /= 7
# Return the ans
print(int(ans % M))
# Driver Code
if __name__ == '__main__':
arr = [1, 3, 3]
N = len(arr)
findSum(arr, N)
# This code is contributed by SURENNDRA_GANGWAR.
2
时间复杂度: O(N * log N)
辅助空间: O(N)