Number of subsets with same AND, OR and XOR values in an Array
Last Updated :
10 May, 2022
Given an array arr[] of size N consisting of non-negative integers, the task is to find the number of non-empty subsets of the array such that the bitwise AND, bitwise OR and bitwise XOR values of the subsequence are equal to each other.
Note: Since the answer can be large, mod it with 1000000007.
Examples:
Input: arr[] = [1, 3, 2, 1, 2, 1]
Output: 7
Explanation:
One of the subsequences with equal bitwise Xor, bitwise or and bitwise AND is {1, 1, 1}.
Input: arr = [2, 3, 4, 5]
Output: 4
Naive Approach The naive approach for this problem is to traverse through all the subsets of the array in an iterative manner, and for each subset find the bitwise AND, OR and XOR value and check whether they are equal or not. Finally, return the count of such equal subsets.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int countSubsets( int a[], int n)
{
int answer = 0;
for ( int i = 0; i < (1 << n); i++) {
int bitwiseAND = -1;
int bitwiseOR = 0;
int bitwiseXOR = 0;
for ( int j = 0; j < n; j++) {
if (i & (1 << j)) {
if (bitwiseAND == -1)
bitwiseAND = a[j];
else
bitwiseAND &= a[j];
bitwiseOR |= a[j];
bitwiseXOR ^= a[j];
}
}
if (bitwiseAND == bitwiseOR
&& bitwiseOR == bitwiseXOR)
answer = (answer + 1) % mod;
}
return answer;
}
int main()
{
int N = 6;
int A[N] = { 1, 3, 2, 1, 2, 1 };
cout << countSubsets(A, N);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int mod = 1000000007 ;
static int countSubsets( int a[], int n)
{
int answer = 0 ;
for ( int i = 0 ; i < ( 1 << n); i++) {
int bitwiseAND = - 1 ;
int bitwiseOR = 0 ;
int bitwiseXOR = 0 ;
for ( int j = 0 ; j < n; j++) {
if ((i & ( 1 << j)) == 0 ) {
if (bitwiseAND == - 1 )
bitwiseAND = a[j];
else
bitwiseAND &= a[j];
bitwiseOR |= a[j];
bitwiseXOR ^= a[j];
}
}
if (bitwiseAND == bitwiseOR
&& bitwiseOR == bitwiseXOR)
answer = (answer + 1 ) % mod;
}
return answer;
}
public static void main (String[] args)
{
int N = 6 ;
int A[] = { 1 , 3 , 2 , 1 , 2 , 1 };
System.out.print(countSubsets(A, N));
}
}
|
Python3
mod = 1000000007 ;
def countSubsets(a, n) :
answer = 0 ;
for i in range ( 1 << n) :
bitwiseAND = - 1 ;
bitwiseOR = 0 ;
bitwiseXOR = 0 ;
for j in range (n) :
if (i & ( 1 << j)) :
if (bitwiseAND = = - 1 ) :
bitwiseAND = a[j];
else :
bitwiseAND & = a[j];
bitwiseOR | = a[j];
bitwiseXOR ^ = a[j];
if (bitwiseAND = = bitwiseOR and bitwiseOR = = bitwiseXOR) :
answer = (answer + 1 ) % mod;
return answer;
if __name__ = = "__main__" :
N = 6 ;
A = [ 1 , 3 , 2 , 1 , 2 , 1 ];
print (countSubsets(A, N));
|
C#
using System;
class GFG {
static int mod = 1000000007;
static int countSubsets( int []a, int n)
{
int answer = 0;
for ( int i = 0; i < (1 << n); i++) {
int bitwiseAND = -1;
int bitwiseOR = 0;
int bitwiseXOR = 0;
for ( int j = 0; j < n; j++) {
if ((i & (1 << j)) == 0) {
if (bitwiseAND == -1)
bitwiseAND = a[j];
else
bitwiseAND &= a[j];
bitwiseOR |= a[j];
bitwiseXOR ^= a[j];
}
}
if (bitwiseAND == bitwiseOR
&& bitwiseOR == bitwiseXOR)
answer = (answer + 1) % mod;
}
return answer;
}
public static void Main(String[] args)
{
int N = 6;
int []A = { 1, 3, 2, 1, 2, 1 };
Console.Write(countSubsets(A, N));
}
}
|
Javascript
<script>
let mod = 1000000007;
function countSubsets(a, n)
{
let answer = 0;
for (let i = 0; i < (1 << n); i++) {
let bitwiseAND = -1;
let bitwiseOR = 0;
let bitwiseXOR = 0;
for (let j = 0; j < n; j++) {
if ((i & (1 << j)) != 0) {
if (bitwiseAND == -1)
bitwiseAND = a[j];
else
bitwiseAND &= a[j];
bitwiseOR |= a[j];
bitwiseXOR ^= a[j];
}
}
if (bitwiseAND == bitwiseOR
&& bitwiseOR == bitwiseXOR)
answer = (answer + 1) % mod;
}
return answer;
}
let N = 6;
let A = [ 1, 3, 2, 1, 2, 1 ];
document.write(countSubsets(A, N));
</script>
|
Time Complexity: O(N * 2N) where N is the size of the array.
Auxiliary Space: O(1)
Efficient Approach: The efficient approach lies behind the property of bitwise operations.
- Using the property of bitwise AND, and bitwise OR we can say that if a & b == a | b, then a is equal to b. So if the AND and OR values of the subset are equal then all the elements of the subset are identical (say x). So the AND and OR values are equal to x.
- Since all the values of subsequence are equal to each other, two case arise for XOR value:
- Subset size is odd: The XOR value equals to x.
- Subset size is even: The XOR values equals to 0.
- Therefore, from the above observation, we can come to the conclusion that all odd-sized subsequences/subsets with equal elements follow the property.
- In addition to this if all the elements of the subset are 0, then the subset will follow the property (irrespective of subset size). So all the subsets which have only 0 as their element will be added to the answer.
- If frequency of some element is K, the then number of odd sized subsets it can form is 2K – 1, and the total non-empty subsets it can form is 2K – 1.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int countSubsets( int a[], int n)
{
int answer = 0;
int powerOfTwo[100005];
powerOfTwo[0] = 1;
for ( int i = 1; i < 100005; i++)
powerOfTwo[i]
= (powerOfTwo[i - 1] * 2)
% mod;
unordered_map< int , int > frequency;
for ( int i = 0; i < n; i++)
frequency[a[i]]++;
for ( auto el : frequency) {
if (el.first != 0)
answer
= (answer % mod
+ powerOfTwo[el.second - 1])
% mod;
else
answer
= (answer % mod
+ powerOfTwo[el.second]
- 1 + mod)
% mod;
}
return answer;
}
int main()
{
int N = 6;
int A[N] = { 1, 3, 2, 1, 2, 1 };
cout << countSubsets(A, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int mod = 1000000007 ;
static int countSubsets( int a[], int n)
{
int answer = 0 ;
int []powerOfTwo = new int [ 100005 ];
powerOfTwo[ 0 ] = 1 ;
for ( int i = 1 ; i < 100005 ; i++)
powerOfTwo[i]
= (powerOfTwo[i - 1 ] * 2 )
% mod;
HashMap<Integer,Integer> frequency = new HashMap<Integer,Integer>();
for ( int i = 0 ; i < n; i++)
if (frequency.containsKey(a[i])){
frequency.put(a[i], frequency.get(a[i])+ 1 );
} else {
frequency.put(a[i], 1 );
}
for (Map.Entry<Integer,Integer> el : frequency.entrySet()) {
if (el.getKey() != 0 )
answer
= (answer % mod
+ powerOfTwo[el.getValue() - 1 ])
% mod;
else
answer
= (answer % mod
+ powerOfTwo[el.getValue()]
- 1 + mod)
% mod;
}
return answer;
}
public static void main(String[] args)
{
int N = 6 ;
int A[] = { 1 , 3 , 2 , 1 , 2 , 1 };
System.out.print(countSubsets(A, N));
}
}
|
Python3
mod = 1000000007
def countSubsets(a, n):
answer = 0
powerOfTwo = [ 0 for x in range ( 100005 )]
powerOfTwo[ 0 ] = 1
for i in range ( 1 , 100005 ):
powerOfTwo[i] = (powerOfTwo[i - 1 ] * 2 ) % mod
frequency = {}
for i in range ( 0 , n):
if a[i] in frequency:
frequency[a[i]] + = 1
else :
frequency[a[i]] = 1
for key, value in frequency.items():
if (key ! = 0 ):
answer = (answer % mod +
powerOfTwo[value - 1 ]) % mod
else :
answer = (answer % mod +
powerOfTwo[value] - 1 + mod) % mod
return answer
N = 6
A = [ 1 , 3 , 2 , 1 , 2 , 1 ]
print (countSubsets(A, N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int mod = 1000000007;
static int countSubsets( int []a, int n)
{
int answer = 0;
int []powerOfTwo = new int [100005];
powerOfTwo[0] = 1;
for ( int i = 1; i < 100005; i++)
powerOfTwo[i] = (powerOfTwo[i - 1] * 2) % mod;
Dictionary< int , int > frequency = new Dictionary< int , int >();
for ( int i = 0; i < n; i++)
if (frequency.ContainsKey(a[i]))
{
frequency[a[i]] = frequency[a[i]] + 1;
}
else
{
frequency.Add(a[i], 1);
}
foreach (KeyValuePair< int , int > el in frequency)
{
if (el.Key != 0)
answer = (answer % mod +
powerOfTwo[el.Value - 1]) % mod;
else
answer = (answer % mod +
powerOfTwo[el.Value] - 1 +
mod) % mod;
}
return answer;
}
public static void Main(String[] args)
{
int N = 6;
int []A = { 1, 3, 2, 1, 2, 1 };
Console.Write(countSubsets(A, N));
}
}
|
Javascript
<script>
var mod = 1000000007;
function countSubsets(a, n)
{
var answer = 0;
var powerOfTwo = Array(100005).fill(0);
powerOfTwo[0] = 1;
for ( var i = 1; i < 100005; i++)
powerOfTwo[i] = (powerOfTwo[i - 1] * 2) % mod;
var frequency = new Map();
for ( var i = 0; i < n; i++)
if (frequency.has(a[i]))
{
frequency.set(a[i], frequency.get(a[i]) + 1);
}
else
{
frequency.set(a[i], 1);
}
frequency.forEach((value, key) => {
if (key != 0)
answer = (answer % mod +
powerOfTwo[value - 1]) % mod;
else
answer = (answer % mod +
powerOfTwo[value] - 1 +
mod) % mod;
});
return answer;
}
var N = 6;
var A = [ 1, 3, 2, 1, 2, 1 ];
document.write(countSubsets(A, N));
</script>
|
Time Complexity: O(N), where N is the size of the array.
Auxiliary Space: O(N + 105)
Share your thoughts in the comments
Please Login to comment...