📜  XOR为零时最大化子数组的数量

📅  最后修改于: 2021-06-25 19:36:50             🧑  作者: Mango

给定一个N个数字的数组。任务是通过任意次数交换任何给定子数组的数组元素的位,以最大化XOR值为零的子数组的数量。
注意: 1 <= A [i] <= 10 18
例子:

方法:第一个观察结果是,在任何给定索引处,偶数个置位比特都可以导致XOR值0。由于数组元素的最大大小可以为10 18左右,因此我们可以假设有60位用于交换。可以按照以下步骤解决上述问题:

  • 由于仅需要设置位的数量,因此请在每个第i个元素中计算设置位的数量。
  • 为了通过交换位使任何子阵列的XOR为零,需要同时满足两个条件。条件如下:
    1. 如果在任何范围的LR中甚至有许多置位的比特,那么我们可以尝试对子数组0进行XOR。
    2. 如果这些位的总和小于或等于任意给定范围内最大置位位数的两倍,则可以将其XOR设为零。

上面已经解释了每个子阵列需要在LR范围内完成的数学工作。
一个简单的解决方案是对每个子数组进行迭代并显式检查两个条件并计算此类子数组的数量。但是这样做的时间复杂度将是O(N ^ 2)。
一个有效的解决方案是遵循以下步骤:

  • 使用prefix [] sum数组可计算仅符合第一个条件的子数组的数量。
  • 1步为我们提供了子数组的数量,它是位的总和,即使O(N)复杂度也是如此。
  • 使用包含-排除原理,我们可以显式减去子数组中2 *最大置位位数超过子数组中置位总和的子数组数。
  • 使用数学运算,我们可以在步骤3中减少子数组检查的次数,因为设置位的数目可以最少为1,所以我们可以检查每个长度为60的子数组,因为超过该长度,第二个条件永远不会被伪造。
  • 完成后,我们可以从步骤1中获得的子数组数量中减去数字,以获得答案。

下面是上述方法的实现:

C++
#include 
using namespace std;
 
// Function to count subarrays not satisfying condition 2
int exclude(int a[], int n)
{
    int count = 0;
    // iterate in the array
    for (int i = 0; i < n; i++) {
 
        // store the sum of set bits
        // in the subarray
        int s = 0;
        int maximum = 0;
 
        // iterate for range of 60 subarrays
        for (int j = i; j < min(n, i + 60); j++) {
            s += a[j];
            maximum = max(a[j], maximum);
 
            // check if falsifies the condition-2
            if (s % 2 == 0 && 2 * maximum > s)
                count++;
        }
    }
 
    return count;
}
 
// Function to count subarrays
int countSubarrays(int a[], int n)
{
 
    // replace the array element by number
    // of set bits in them
    for (int i = 0; i < n; i++)
        a[i] = __builtin_popcountll(a[i]);
 
    // calculate prefix array
    int pre[n];
    for (int i = 0; i < n; i++) {
        pre[i] = a[i];
        if (i != 0)
 
            pre[i] += pre[i - 1];
    }
 
    // Count the number of subarays
    // satisfying step-1
    int odd = 0, even = 0;
 
    // count number of odd and even
    for (int i = 0; i < n; i++) {
        if (pre[i] & 1)
            odd++;
    }
    even = n - odd;
 
    // Increase even by 1 for 1, so that the
    // subarrys starting from the index-0
    // are also taken to count
    even++;
 
    // total subarrays satsfying condition-1 only
    int answer = (odd * (odd - 1) / 2) + (even * (even - 1) / 2);
 
    cout << answer << endl;
 
    // exclude total subarrays not satsfying condition2
    answer = answer - exclude(a, n);
 
    return answer;
}
 
// Driver Code
int main()
{
 
    int a[] = { 6, 7, 14 };
    int n = sizeof(a) / sizeof(a[0]);
 
    cout << countSubarrays(a, n);
 
    return 0;
}


Java
// Java Program to find the minimum element to
// be added such that the array can be partitioned
// into two contiguous subarrays with equal sums
import java.util.*;
 
class GFG
{
 
// Function to count subarrays not satisfying condition 2
static int exclude(int a[], int n)
{
    int count = 0;
    // iterate in the array
    for (int i = 0; i < n; i++)
    {
 
        // store the sum of set bits
        // in the subarray
        int s = 0;
        int maximum = 0;
 
        // iterate for range of 60 subarrays
        for (int j = i; j < Math.min(n, i + 60); j++)
        {
            s += a[j];
            maximum = Math.max(a[j], maximum);
 
            // check if falsifies the condition-2
            if (s % 2 == 0 && 2 * maximum > s)
                count++;
        }
    }
 
    return count;
}
 
// Function to count subarrays
static int countSubarrays(int a[], int n)
{
 
    // replace the array element by number
    // of set bits in them
    for (int i = 0; i < n; i++)
        a[i] = Integer.bitCount(a[i]);
 
    // calculate prefix array
    int []pre = new int[n];
    for (int i = 0; i < n; i++)
    {
        pre[i] = a[i];
        if (i != 0)
 
            pre[i] += pre[i - 1];
    }
 
    // Count the number of subarays
    // satisfying step-1
    int odd = 0, even = 0;
 
    // count number of odd and even
    for (int i = 0; i < n; i++)
    {
        if (pre[i]%2== 1)
            odd++;
    }
    even = n - odd;
 
    // Increase even by 1 for 1, so that the
    // subarrys starting from the index-0
    // are also taken to count
    even++;
 
    // total subarrays satsfying condition-1 only
    int answer = (odd * (odd - 1) / 2) + (even * (even - 1) / 2);
 
    System.out.println(answer);
 
    // exclude total subarrays not satsfying condition2
    answer = answer - exclude(a, n);
 
    return answer;
}
 
// Driver Code
public static void main(String[] args)
{
    int a[] = { 6, 7, 14 };
    int n = a.length;
 
    System.out.println(countSubarrays(a, n));
}
}
 
// This code is contributed by Rajput-Ji


Python3
# Python3 code for the given approach.
 
# Function to count subarrays not
# satisfying condition 2
def exclude(a, n):
 
    count = 0
     
    # iterate in the array
    for i in range(0, n):
 
        # store the sum of set bits
        # in the subarray
        s = 0
        maximum = 0
 
        # iterate for range of 60 subarrays
        for j in range(i, min(n, i + 60)):
            s += a[j]
            maximum = max(a[j], maximum)
 
            # check if falsifies the condition-2
            if s % 2 == 0 and 2 * maximum > s:
                count += 1
 
    return count
 
# Function to count subarrays
def countSubarrays(a, n):
 
    # replace the array element by
    # number of set bits in them
    for i in range(0, n):
        a[i] = bin(a[i]).count('1')
 
    # calculate prefix array
    pre = [None] * n
    for i in range(0, n):
        pre[i] = a[i]
         
        if i != 0:
            pre[i] += pre[i - 1]
     
    # Count the number of subarays
    # satisfying step-1
    odd, even = 0, 0
 
    # count number of odd and even
    for i in range(0, n):
        if pre[i] & 1:
            odd += 1
     
    even = n - odd
 
    # Increase even by 1 for 1, so that the
    # subarrys starting from the index-0
    # are also taken to count
    even += 1
 
    # total subarrays satsfying condition-1 only
    answer = ((odd * (odd - 1) // 2) +
             (even * (even - 1) // 2))
 
    print(answer)
 
    # exclude total subarrays not
    # satsfying condition2
    answer = answer - exclude(a, n)
 
    return answer
 
# Driver Code
if __name__ == "__main__":
 
    a = [6, 7, 14]
    n = len(a)
 
    print(countSubarrays(a, n))
     
# This code is contributed by Rituraj Jain


C#
// C# Program to find the minimum element to
// be added such that the array can be partitioned
// into two contiguous subarrays with equal sums
using System;
     
class GFG
{
 
// Function to count subarrays not satisfying condition 2
static int exclude(int []a, int n)
{
    int count = 0;
    // iterate in the array
    for (int i = 0; i < n; i++)
    {
 
        // store the sum of set bits
        // in the subarray
        int s = 0;
        int maximum = 0;
 
        // iterate for range of 60 subarrays
        for (int j = i; j < Math.Min(n, i + 60); j++)
        {
            s += a[j];
            maximum = Math.Max(a[j], maximum);
 
            // check if falsifies the condition-2
            if (s % 2 == 0 && 2 * maximum > s)
                count++;
        }
    }
 
    return count;
}
 
// Function to count subarrays
static int countSubarrays(int []a, int n)
{
 
    // replace the array element by number
    // of set bits in them
    for (int i = 0; i < n; i++)
        a[i] = bitCount(a[i]);
 
    // calculate prefix array
    int []pre = new int[n];
    for (int i = 0; i < n; i++)
    {
        pre[i] = a[i];
        if (i != 0)
 
            pre[i] += pre[i - 1];
    }
 
    // Count the number of subarays
    // satisfying step-1
    int odd = 0, even = 0;
 
    // count number of odd and even
    for (int i = 0; i < n; i++)
    {
        if (pre[i]%2== 1)
            odd++;
    }
    even = n - odd;
 
    // Increase even by 1 for 1, so that the
    // subarrys starting from the index-0
    // are also taken to count
    even++;
 
    // total subarrays satsfying condition-1 only
    int answer = (odd * (odd - 1) / 2) + (even * (even - 1) / 2);
 
    Console.WriteLine(answer);
 
    // exclude total subarrays not satsfying condition2
    answer = answer - exclude(a, n);
 
    return answer;
}
 
static int bitCount(long x)
{
    int setBits = 0;
    while (x != 0) {
        x = x & (x - 1);
        setBits++;
    }
    return setBits;
}
 
// Driver Code
public static void Main(String[] args)
{
    int []a = { 6, 7, 14 };
    int n = a.Length;
 
    Console.WriteLine(countSubarrays(a, n));
}
}
 
// This code is contributed by Rajput-Ji


Javascript


输出:
3
2

时间复杂度: O(N * 60)

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。