对于 Q 查询,其 XOR 甚至在 [L, R] 范围内设置位的三元组计数
给定一个大小为N的数组arr[]和一个由M个{L, R}类型的查询组成的数组Q[] ,任务是打印三元组的计数,其 XOR 在范围[ L, R] ,用于M个查询中的每一个。
例子:
Input: arr[] = {1, 2, 3, 4, 5}, N = 5, Q[] = {{1, 4}, {3, 4}}, M = 2
Output: 3
0
Explanation:
Perform the query as following:
- Query(1, 4): Print 3. The triplets whose xor has an even number of set bits are {1, 2, 3}, {1, 3, 4} and {2, 3, 4}.
- Query(3, 4): Print 0. There are no triplets that satisfy the condition.
Input: arr[] = {3, 3, 3}, N = 2, Q[] = {{1, 3}}, M = 1
Output: 1
方法:可以根据以下观察解决给定的问题:
- 两个数X和Y的异或,即X^Y只有在以下情况下才能有偶数个设置位:
- X和Y都有偶数个设置位。
- X和Y都有奇数个设置位。
- 因此,仅存在三个数字的 XOR 具有偶数个设置位的情况,即:
- 所有三个数字都有偶数个设置位。
- 恰好其中两个具有奇数个设置位,另一个具有偶数个设置位。
- 因此,通过应用上述观察,可以用前缀数组的概念来解决这个问题。
请按照以下步骤解决问题:
- 初始化一个大小为N+1的前缀数组preo[] ,其中preo[i]存储直到索引i的元素数量,这些元素具有奇数个 set bits 。
- 创建另一个前缀数组,说大小为N+1的pree ,其中pree[i]存储直到索引i的元素数量,这些元素具有偶数个设置位。
- 遍历数组 arr[],并执行以下操作:
- 使用__builtin_popcount() 函数计算当前元素中设置的位数。
- 如果设置的位数是奇数,则增加preo[i]
- 否则,增加pree[i]
- 遍历数组Q[]并执行以下步骤:
- 使用preo[]数组计算具有奇数个设置位的元素的数量并将其存储在一个变量中,比如奇数。
- 使用pree []数组计算具有偶数个设置位的元素的数量并将其存储在一个变量中,比如 even 。
- 将变量ans初始化为0以存储三元组的计数。
- 如果even不小于3 ,则将even C 3添加到ans中。
- 如果even不小于1 , odd不小于2 ,则将( odd C 2 )*( even C 1 )添加到ans 。
- 最后,打印当前查询{L, R}在ans中获得的三元组的计数。
以下是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Utility function to calculate NCR
int NCR(int N, int R)
{
if (R > N - R)
R = N - R;
int ans = 1;
for (int i = 1; i <= R; i++) {
ans *= N - R + i;
ans /= i;
}
return ans;
}
// Function to answer queries about
// the number of triplets in range
// whose XOR has an even number of
// set bits
void solveXorTriplets(int arr[], int N,
vector > Q, int M)
{
// Prefix arrays to store
// number that have odd
// and even setbits
int preo[N + 1] = { 0 };
int pree[N + 1] = { 0 };
// Traverse the array arr[]
for (int i = 0; i < N; i++) {
// Update
preo[i + 1] += preo[i];
pree[i + 1] += pree[i];
// Find bits in current
// element
int setbits = __builtin_popcount(arr[i]);
// If number of setbits
// is odd
if (setbits % 2)
preo[i + 1]++;
// Otherwise
else
pree[i + 1]++;
}
// Traverse the query Q[][]
for (int i = 0; i < M; i++) {
// Stores Left boundary
int L = Q[i].first;
// Stores Right boundary
int R = Q[i].second;
// Stores number of elements
// that have odd set bits in
// the given range
int odd = preo[R] - preo[L - 1];
// Store number of elements
// that have even set bits
// in given range
int even = pree[R] - pree[L - 1];
// Store the count
// of the triplets
int ans = 0;
// If even is greater
// than ore equal to 3
if (even >= 3)
ans += NCR(even, 3);
// If odd is greater than
// or equal to and even is
// greater than or equal to
// 1
if (odd >= 2 && even >= 1)
ans += NCR(odd, 2) * NCR(even, 1);
// Print the answer
// for current query
cout << ans << endl;
}
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int N = sizeof(arr) / sizeof(arr[0]);
vector > Q = { { 1, 4 }, { 3, 4 } };
int M = Q.size();
solveXorTriplets(arr, N, Q, M);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
static class pair
{
int first, second;
public pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
// Utility function to calculate NCR
static int NCR(int N, int R)
{
if (R > N - R)
R = N - R;
int ans = 1;
for(int i = 1; i <= R; i++)
{
ans *= N - R + i;
ans /= i;
}
return ans;
}
// Function to answer queries about
// the number of triplets in range
// whose XOR has an even number of
// set bits
static void solveXorTriplets(int arr[], int N,
Vector Q, int M)
{
// Prefix arrays to store
// number that have odd
// and even setbits
int preo[] = new int[N + 1];
int pree[] = new int[N + 1];
// Traverse the array arr[]
for(int i = 0; i < N; i++)
{
// Update
preo[i + 1] += preo[i];
pree[i + 1] += pree[i];
// Find bits in current
// element
int setbits = Integer.bitCount(arr[i]);
// If number of setbits
// is odd
if (setbits % 2 != 0)
preo[i + 1]++;
// Otherwise
else
pree[i + 1]++;
}
// Traverse the query Q[][]
for(int i = 0; i < M; i++)
{
// Stores Left boundary
int L = Q.elementAt(i).first;
// Stores Right boundary
int R = Q.elementAt(i).second;
// Stores number of elements
// that have odd set bits in
// the given range
int odd = preo[R] - preo[L - 1];
// Store number of elements
// that have even set bits
// in given range
int even = pree[R] - pree[L - 1];
// Store the count
// of the triplets
int ans = 0;
// If even is greater
// than ore equal to 3
if (even >= 3)
ans += NCR(even, 3);
// If odd is greater than
// or equal to and even is
// greater than or equal to
// 1
if (odd >= 2 && even >= 1)
ans += NCR(odd, 2) * NCR(even, 1);
// Print the answer
// for current query
System.out.println(ans);
}
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 1, 2, 3, 4, 5 };
int N = arr.length;
Vector Q = new Vector<>();
Q.add(new pair(1, 4));
Q.add(new pair(3, 4));
int M = Q.size();
solveXorTriplets(arr, N, Q, M);
}
}
// This code is contributed by Dharanendra L V.
Python3
# Python3 program for the above approach
# Utility function to calculate NCR
def NCR(N, R):
if (R > N - R):
R = N - R
ans = 1
for i in range(1,R+1):
ans *= N - R + i
ans //= i
return ans
# Function to answer queries about
# the number of triplets in range
# whose XOR has an even number of
# set bits
def solveXorTriplets(arr, N, Q, M):
# Prefix arrays to store
# number that have odd
# and even setbits
preo = [0]*(N + 1)
pree = [0]*(N + 1)
# Traverse the array arr[]
for i in range(N):
preo[i + 1] += preo[i]
pree[i + 1] += pree[i]
# Find bits in current
# element
setbits =bin(arr[i]).count('1')
# If number of setbits
# is odd
if (setbits % 2):
preo[i + 1] +=1
# Otherwise
else:
pree[i + 1]+=1
# Traverse the query Q[][]
for i in range(M):
# Stores Left boundary
L = Q[i][0]
# Stores Right boundary
R = Q[i][1]
# Stores number of elements
# that have odd set bits in
# the given range
odd = preo[R] - preo[L - 1]
# Store number of elements
# that have even set bits
# in given range
even = pree[R] - pree[L - 1]
# Store the count
# of the triplets
ans = 0
# If even is greater
# than ore equal to 3
if (even >= 3):
ans += NCR(even, 3)
# If odd is greater than
# or equal to and even is
# greater than or equal to
# 1
if (odd >= 2 and even >= 1):
ans += NCR(odd, 2) * NCR(even, 1)
# Print answer
# for current query
print (ans)
# Driver Code
if __name__ == '__main__':
arr = [1, 2, 3, 4, 5]
N = len(arr)
Q = [ [ 1, 4 ], [ 3, 4 ] ]
M = len(Q)
solveXorTriplets(arr, N, Q, M)
# This code is contributed by mohit kumar 29.
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class pair{
int first, second;
pair(int first, int second)
{
this.first = first;
this.second = second;
}
public static int BitCount(int n)
{
var count = 0;
while (n != 0)
{
count++;
n &= (n - 1); //walking through all the bits which are set to one
}
return count;
}
// Utility function to calculate NCR
static int NCR(int N, int R)
{
if (R > N - R)
R = N - R;
int ans = 1;
for(int i = 1; i <= R; i++)
{
ans *= N - R + i;
ans /= i;
}
return ans;
}
// Function to answer queries about
// the number of triplets in range
// whose XOR has an even number of
// set bits
static void solveXorTriplets(int[] arr, int N,
List Q, int M)
{
// Prefix arrays to store
// number that have odd
// and even setbits
int[] preo = new int[N + 1];
int[] pree = new int[N + 1];
// Traverse the array arr[]
for(int i = 0; i < N; i++)
{
// Update
preo[i + 1] += preo[i];
pree[i + 1] += pree[i];
// Find bits in current
// element
int setbits = BitCount(arr[i]);
// If number of setbits
// is odd
if (setbits % 2 != 0)
preo[i + 1]++;
// Otherwise
else
pree[i + 1]++;
}
// Traverse the query Q[][]
for(int i = 0; i < M; i++)
{
// Stores Left boundary
int L = Q[i].first;
// Stores Right boundary
int R = Q[i].second;
// Stores number of elements
// that have odd set bits in
// the given range
int odd = preo[R] - preo[L - 1];
// Store number of elements
// that have even set bits
// in given range
int even = pree[R] - pree[L - 1];
// Store the count
// of the triplets
int ans = 0;
// If even is greater
// than ore equal to 3
if (even >= 3)
ans += NCR(even, 3);
// If odd is greater than
// or equal to and even is
// greater than or equal to
// 1
if (odd >= 2 && even >= 1)
ans += NCR(odd, 2) * NCR(even, 1);
// Print the answer
// for current query
Console.WriteLine(ans);
}
}
// Driver Code
public static void Main()
{
int[] arr = { 1, 2, 3, 4, 5 };
int N = arr.Length;
List Q = new List();
Q.Add(new pair(1, 4));
Q.Add(new pair(3, 4));
int M = Q.Count;
solveXorTriplets(arr, N, Q, M);
}
}
// This code is contributed by ShubhamSingh10
C++
#include
using namespace std;
int main() {
cout<<"GFG!";
return 0;
}
Javascript
输出
3
0
时间复杂度: O(N+M)
辅助空间: O(N)