Count no. of ordered subsets having a particular XOR value
Given an array arr[] of n elements and a number K, find the number of ordered subsets of arr[] having XOR of elements as K
This is a modified version of this problem. So it is recommended to try that problem before.
Examples:
Input: arr[] = {6, 9, 4, 2}, k = 6
Output: 2
The subsets are {4, 2}, {2, 4} and {6}
Input: arr[] = {1, 2, 3}, k = 1
Output: 4
The subsets are {1}, {2, 3} and {3, 2}
Naive Approach O(2n): Generate all the 2n subsets and find all the subsets having XOR value K and for each subset with XOR value K, add no. of permutations of that subset to the answer since we are required ordered subsets, but this approach will not be efficient for large values of n.
Efficient Approach O(n2 * m): This approach uses dynamic programming which is similar to the approach explained in this article.
Only modification is that we add one more state to our solution. There we had two states where dp[i][j] stored the no. of subsets of the array[0…i-1] having XOR value j. Now, we add one more state k, i.e. a third dimension that stores the length of the subsets.
So, dp[i][j][k] will store the no. of subsets of length k of the array[0…i-1] having XOR value j.
Now we can see that,
i.e.
dp[i][j][k] can be found by discarding the
a[i] element(which gives dp[i-1][j][k] subsets) and taking it in the subset(Similar idea to Subset Sum Problem) which gives
dp[i-1][a[i] ^ j][k-1] subsets. Now we have to insert the
a[i] element in the
k – 1 length subsets which can be done in
k ways which explains the factor of k.
After computing the
dp array, our answer will be
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int subsetXOR( int arr[], int n, int K)
{
int max_ele = arr[0];
for ( int i = 1; i < n; i++)
if (arr[i] > max_ele)
max_ele = arr[i];
int m = (1 << ( int )(log2(max_ele) + 1)) - 1;
int dp[n + 1][m + 1][n + 1];
for ( int i = 0; i <= n; i++)
for ( int j = 0; j <= m; j++)
for ( int k = 0; k <= n; k++)
dp[i][j][k] = 0;
for ( int i = 0; i <= n; i++)
dp[i][0][0] = 1;
for ( int i = 1; i <= n; i++) {
for ( int j = 0; j <= m; j++) {
for ( int k = 0; k <= n; k++) {
dp[i][j][k] = dp[i - 1][j][k];
if (k != 0) {
dp[i][j][k] += k * dp[i - 1][j ^
arr[i - 1]][k - 1];
}
}
}
}
int ans = 0;
for ( int i = 1; i <= n; i++) {
ans += dp[n][K][i];
}
return ans;
}
int main()
{
int arr[] = { 1, 2, 3 };
int k = 1;
int n = sizeof (arr) / sizeof (arr[0]);
cout << subsetXOR(arr, n, k);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int subsetXOR( int arr[], int n, int K)
{
int max_ele = arr[ 0 ];
for ( int i = 1 ; i < n; i++)
if (arr[i] > max_ele)
max_ele = arr[i];
int m = ( 1 << ( int )(Math.log(max_ele) /
Math.log( 2 ) + 1 )) - 1 ;
int [][][] dp = new int [n + 1 ][m + 1 ][n + 1 ];
for ( int i = 0 ; i <= n; i++)
for ( int j = 0 ; j <= m; j++)
for ( int k = 0 ; k <= n; k++)
dp[i][j][k] = 0 ;
for ( int i = 0 ; i <= n; i++)
dp[i][ 0 ][ 0 ] = 1 ;
for ( int i = 1 ; i <= n; i++)
{
for ( int j = 0 ; j <= m; j++)
{
for ( int k = 0 ; k <= n; k++)
{
dp[i][j][k] = dp[i - 1 ][j][k];
if (k != 0 )
{
dp[i][j][k] += k * dp[i - 1 ][j ^
arr[i - 1 ]][k - 1 ];
}
}
}
}
int ans = 0 ;
for ( int i = 1 ; i <= n; i++)
{
ans += dp[n][K][i];
}
return ans;
}
public static void main(String []args)
{
int arr[] = { 1 , 2 , 3 };
int k = 1 ;
int n = arr.length;
System.out.println(subsetXOR(arr, n, k));
}
}
|
Python3
from math import log2
def subsetXOR(arr, n, K):
max_ele = arr[ 0 ]
for i in range ( 1 , n):
if (arr[i] > max_ele):
max_ele = arr[i]
m = ( 1 << int (log2(max_ele) + 1 )) - 1
dp = [[[ 0 for i in range (n + 1 )]
for j in range (m + 1 )]
for k in range (n + 1 )]
for i in range (n + 1 ):
for j in range (m + 1 ):
for k in range (n + 1 ):
dp[i][j][k] = 0
for i in range (n + 1 ):
dp[i][ 0 ][ 0 ] = 1
for i in range ( 1 , n + 1 ):
for j in range (m + 1 ):
for k in range (n + 1 ):
dp[i][j][k] = dp[i - 1 ][j][k]
if (k ! = 0 ):
dp[i][j][k] + = k * dp[i - 1 ][j ^ arr[i - 1 ]][k - 1 ]
ans = 0
for i in range ( 1 , n + 1 ):
ans + = dp[n][K][i]
return ans
if __name__ = = '__main__' :
arr = [ 1 , 2 , 3 ]
k = 1
n = len (arr)
print (subsetXOR(arr, n, k))
|
C#
using System;
class GFG
{
static int subsetXOR( int []arr, int n, int K)
{
int max_ele = arr[0];
for ( int i = 1; i < n; i++)
if (arr[i] > max_ele)
max_ele = arr[i];
int m = (1 << ( int )(Math.Log(max_ele) /
Math.Log(2) + 1)) - 1;
int [ , , ] dp = new int [n + 1 , m + 1 ,n + 1];
for ( int i = 0; i <= n; i++)
for ( int j = 0; j <= m; j++)
for ( int k = 0; k <= n; k++)
dp[i, j, k] = 0;
for ( int i = 0; i <= n; i++)
dp[i, 0, 0] = 1;
for ( int i = 1; i <= n; i++)
{
for ( int j = 0; j <= m; j++)
{
for ( int k = 0; k <= n; k++)
{
dp[i, j, k] = dp[i - 1, j, k];
if (k != 0) {
dp[i, j, k] += k * dp[i - 1, j ^
arr[i - 1], k - 1];
}
}
}
}
int ans = 0;
for ( int i = 1; i <= n; i++)
{
ans += dp[n, K, i];
}
return ans;
}
public static void Main()
{
int []arr = { 1, 2, 3 };
int k = 1;
int n = arr.Length;
Console.WriteLine(subsetXOR(arr, n, k));
}
}
|
PHP
<?php
function subsetXOR( $arr , $n , $K )
{
$max_ele = $arr [0];
for ( $i = 1; $i < $n ; $i ++)
if ( $arr [ $i ] > $max_ele )
$max_ele = $arr [ $i ];
$m = (1 << ( floor (log( $max_ele , 2))+ 1)) - 1;
$dp = array ( array ( array ())) ;
for ( $i = 0; $i <= $n ; $i ++)
for ( $j = 0; $j <= $m ; $j ++)
for ( $k = 0; $k <= $n ; $k ++)
$dp [ $i ][ $j ][ $k ] = 0;
for ( $i = 0; $i <= $n ; $i ++)
$dp [ $i ][0][0] = 1;
for ( $i = 1; $i <= $n ; $i ++)
{
for ( $j = 0; $j <= $m ; $j ++)
{
for ( $k = 0; $k <= $n ; $k ++)
{
$dp [ $i ][ $j ][ $k ] = $dp [ $i - 1][ $j ][ $k ];
if ( $k != 0)
{
$dp [ $i ][ $j ][ $k ] += $k * $dp [ $i - 1][ $j ^
$arr [ $i - 1]][ $k - 1];
}
}
}
}
$ans = 0;
for ( $i = 1; $i <= $n ; $i ++)
{
$ans += $dp [ $n ][ $K ][ $i ];
}
return $ans ;
}
$arr = [ 1, 2, 3 ];
$k = 1;
$n = sizeof( $arr );
echo subsetXOR( $arr , $n , $k );
?>
|
Javascript
<script>
function subsetXOR(arr, n, K)
{
let max_ele = arr[0];
for (let i = 1; i < n; i++)
if (arr[i] > max_ele)
max_ele = arr[i];
let m =
(1 << parseInt(Math.log(max_ele) / Math.log(2) + 1, 10)) - 1;
let dp = new Array(n + 1);
for (let i = 0; i <= n; i++)
{
dp[i] = new Array(m + 1);
for (let j = 0; j <= m; j++)
{
dp[i][j] = new Array(n + 1);
for (let k = 0; k <= n; k++)
{
dp[i][j][k] = 0;
}
}
}
for (let i = 0; i <= n; i++)
dp[i][0][0] = 1;
for (let i = 1; i <= n; i++)
{
for (let j = 0; j <= m; j++)
{
for (let k = 0; k <= n; k++)
{
dp[i][j][k] = dp[i - 1][j][k];
if (k != 0)
{
dp[i][j][k] += k * dp[i - 1][j ^
arr[i - 1]][k - 1];
}
}
}
}
let ans = 0;
for (let i = 1; i <= n; i++)
{
ans += dp[n][K][i];
}
return ans;
}
let arr = [ 1, 2, 3 ];
let k = 1;
let n = arr.length;
document.write(subsetXOR(arr, n, k));
</script>
|
Time Complexity: O(n2 * m)
Auxiliary Space: O(n2 * m)
Last Updated :
18 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...