📌  相关文章
📜  对于 Q 查询,其 XOR 甚至在 [L, R] 范围内设置位的三元组计数

📅  最后修改于: 2022-05-13 01:56:10.770000             🧑  作者: Mango

对于 Q 查询,其 XOR 甚至在 [L, R] 范围内设置位的三元组计数

给定一个大小为N的数组arr[]和一个由M{L, R}类型的查询组成的数组Q[] ,任务是打印三元组的计数,其 XOR 在范围[ L, R] ,用于M个查询中的每一个。

例子:

方法:可以根据以下观察解决给定的问题:

  1. 两个数XY的异或,即X^Y只有在以下情况下才能有偶数个设置位:
    1. XY都有偶数个设置位
    2. XY都有奇数个设置位
  2. 因此,仅存在三个数字的 XOR 具有偶数个设置位的情况,即:
    1. 所有三个数字都有偶数个设置位
    2. 恰好其中两个具有奇数个设置位,另一个具有偶数个设置位
  3. 因此,通过应用上述观察,可以用前缀数组的概念来解决这个问题。

请按照以下步骤解决问题:

  • 初始化一个大小为N+1的前缀数组preo[] ,其中preo[i]存储直到索引i的元素数量,这些元素具有奇数个 set bits
  • 创建另一个前缀数组,说大小为N+1pree ,其中pree[i]存储直到索引i的元素数量,这些元素具有偶数个设置位。
  • 遍历数组 arr[],并执行以下操作:
    • 使用__builtin_popcount() 函数计算当前元素中设置的位数。
    • 如果设置的位数是奇数,则增加preo[i]
    • 否则,增加pree[i]
  • 遍历数组Q[]并执行以下步骤:
    • 使用preo[]数组计算具有奇数个设置位的元素的数量并将其存储在一个变量中,比如奇数
    • 使用pree []数组计算具有偶数个设置位的元素的数量并将其存储在一个变量中,比如 even
    • 将变量ans初始化为0以存储三元组的计数。
    • 如果even不小于3 ,则将even C 3添加到ans中。
    • 如果even不小于1odd不小于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)