Count pairs up to N having sum equal to their XOR
Last Updated :
05 Oct, 2021
Given an integer N, the task is to count the number of pairs (X, Y) such that X + Y = X ^ Y and X + Y ? N.
Note: ^ denotes Bitwise xor.
Examples:
Input: N = 3
Output: 9
Explanation: The pairs satisfying the given conditions are {{0, 0}, {0, 1}, {1, 0}, {0, 2}, {2, 0}, {3, 0}, {0, 3}, {2, 1}, {1, 2}}
Input: N = 10
Output: 37
Naive Approach: The simplest approach is to generate all possible pairs (X, Y) and check if the conditions X + Y = X ^ Y and X + Y ? N are satisfied or not.
Time Complexity: O(N2)
Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized based on the observation that X+Y ? X ^ Y for any value of X and Y. Consider the binary representation of X and Y. Let bit(X, pos) and bit(Y, pos) be the bits corresponding to X and Y at some fixed position pos. The condition X+Y = X^Y will be only satisfied if {bit(X, pos), bit(Y, pos)} ? {{1, 0}, {0, 1}, {0, 0}}. In other words, both X and Y cannot have set bits at the same positions.
In the efficient approach, the problem can be solved using Dynamic Programming. The problems have overlapping subproblems and optimal substructure. The subproblems are stored in a dp[][] table using memoization where dp[i][bound] stores the answer from the ‘i’th position to the end and bound is a boolean variable to ensure that the sum of numbers does not exceed N.
- Convert the limit N into its binary representation. Store the binary representation in a string, say S, so that iterating only over the length of the string and not the actual limit will be sufficient.
- Define a recursive function IsSumEqualsXor(i, bound) by performing the following steps.
- Check the base cases, if i == length of S then return 1, as a valid pair has been formed.
- If the result of the state dp[i][bound] has already been computed, then return the state dp[i][bound].
- At the current position i, any of the three pairs among {{0, 0}, {0, 1}, {1, 0}} can be assigned by checking few conditions. They are
- If the bound is true and the current character in S i.e S[i] is ‘0’ then, only {0, 0} can be placed as a valid pair in the current position. That is done to ensure that the sum does not exceed N.
- Otherwise, any pair among {{0, 0}, {0, 1}, {1, 0}} can be placed and bound is set to true or false accordingly.
- After placing a valid pair in the current position, recursively call the IsSumEqualsXor function for the element at index (i + 1).
- Return the sum of all possible valid placements of digits as the answer.
Below is the implementation of the above approach :
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1000][2];
int IsSumEqualsXor( int i, int n,
bool bound, string& s)
{
if (i == n)
return 1;
if (dp[i][bound] != -1)
return dp[i][bound];
int ans = 0;
if (bound and s[i] == '0' ) {
ans = IsSumEqualsXor(i + 1, n, 1, s);
}
else {
ans = 2
* IsSumEqualsXor(i + 1, n,
bound & (s[i] == '1' ), s);
ans += IsSumEqualsXor(i + 1, n, 0, s);
}
return dp[i][bound] = ans;
}
string convertToBinary( int n)
{
string ans;
while (n) {
char rem = char (n % 2 + '0' );
ans.push_back(rem);
n /= 2;
}
reverse(ans.begin(), ans.end());
return ans;
}
void IsSumEqualsXorUtil( int N)
{
string s = convertToBinary(N);
memset (dp, -1, sizeof dp);
cout << IsSumEqualsXor(0, s.size(), 1, s) << endl;
}
int main()
{
int N = 10;
IsSumEqualsXorUtil(N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int [][]dp = new int [ 1000 ][ 2 ];
static int IsSumEqualsXor( int i, int n,
int bound, char [] s)
{
if (i == n)
return 1 ;
if (dp[i][bound] != - 1 )
return dp[i][bound];
int ans = 0 ;
if (bound!= 0 && s[i] == '0' ) {
ans = IsSumEqualsXor(i + 1 , n, 1 , s);
}
else {
ans = 2
* IsSumEqualsXor(i + 1 , n,
bound!= 0 & (s[i] == '1' )? 1 : 0 , s);
ans += IsSumEqualsXor(i + 1 , n, 0 , s);
}
return dp[i][bound] = ans;
}
static String reverse(String input) {
char [] a = input.toCharArray();
int l, r = a.length - 1 ;
for (l = 0 ; l < r; l++, r--) {
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return String.valueOf(a);
}
static String convertToBinary( int n)
{
String ans= "" ;
while (n> 0 ) {
char rem = ( char )(n % 2 + '0' );
ans+=(rem);
n /= 2 ;
}
ans = reverse(ans);
return ans;
}
static void IsSumEqualsXorUtil( int N)
{
String s = convertToBinary(N);
for ( int i = 0 ; i < dp.length; i++)
{
for ( int j = 0 ; j < dp[ 0 ].length; j++) {
dp[i][j] = - 1 ;
}
}
System.out.print(IsSumEqualsXor( 0 , s.length(), 1 , s.toCharArray()) + "\n" );
}
public static void main(String[] args)
{
int N = 10 ;
IsSumEqualsXorUtil(N);
}
}
|
Python3
dp = [[ - 1 for i in range ( 2 )]
for j in range ( 1000 )]
def IsSumEqualsXor(i, n, bound, s):
if (i = = n):
return 1
if (dp[i][bound] ! = - 1 ):
return dp[i][bound]
ans = 0
if (bound and s[i] = = '0' ):
ans = IsSumEqualsXor(i + 1 , n, 1 , s)
else :
ans = 2 * IsSumEqualsXor(
i + 1 , n, bound & (s[i] = = '1' ), s)
ans + = IsSumEqualsXor(i + 1 , n, 0 , s)
dp[i][bound] = ans
return ans
def convertToBinary(n):
ans = []
while (n):
rem = chr (n % 2 + 48 )
ans.append(rem)
n / / = 2
ans = ans[:: - 1 ]
return ans
def IsSumEqualsXorUtil(N):
s = convertToBinary(N)
print (IsSumEqualsXor( 0 , len (s), 1 , s))
if __name__ = = '__main__' :
N = 10
IsSumEqualsXorUtil(N)
|
C#
using System;
class GFG{
static int [,]dp = new int [1000, 2];
static int IsSumEqualsXor( int i, int n,
int bound, char [] s)
{
if (i == n)
return 1;
if (dp[i,bound] != -1)
return dp[i,bound];
int ans = 0;
if (bound != 0 && s[i] == '0' )
{
ans = IsSumEqualsXor(i + 1, n, 1, s);
}
else
{
ans = 2 * IsSumEqualsXor(i + 1, n,
bound != 0 &
(s[i] == '1' ) ? 1 : 0, s);
ans += IsSumEqualsXor(i + 1, n, 0, s);
}
return dp[i, bound] = ans;
}
static String reverse(String input)
{
char [] a = input.ToCharArray();
int l, r = a.Length - 1;
for (l = 0; l < r; l++, r--)
{
char temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return String.Join( "" , a);
}
static String convertToBinary( int n)
{
String ans = "" ;
while (n > 0)
{
char rem = ( char )(n % 2 + '0' );
ans += (rem);
n /= 2;
}
ans = reverse(ans);
return ans;
}
static void IsSumEqualsXorUtil( int N)
{
String s = convertToBinary(N);
for ( int i = 0; i < dp.GetLength(0); i++)
{
for ( int j = 0; j < dp.GetLength(1); j++)
{
dp[i, j] = -1;
}
}
Console.Write(IsSumEqualsXor(0, s.Length, 1,
s.ToCharArray()) + "\n" );
}
public static void Main(String[] args)
{
int N = 10;
IsSumEqualsXorUtil(N);
}
}
|
Javascript
<script>
let dp = new Array(1000);
for (let i = 0; i < 1000; i++)
{
dp[i] = new Array(2);
}
function IsSumEqualsXor(i, n, bound, s)
{
if (i == n)
return 1;
if (dp[i][bound] != -1)
return dp[i][bound];
let ans = 0;
if (bound!=0 && s[i] == '0' ) {
ans = IsSumEqualsXor(i + 1, n, 1, s);
}
else {
ans = 2
* IsSumEqualsXor(i + 1, n,
bound!=0 & (s[i] == '1' )?1:0, s);
ans += IsSumEqualsXor(i + 1, n, 0, s);
}
dp[i][bound] = ans
return dp[i][bound];
}
function reverse(input) {
let a = input.split( '' );
let l, r = a.length - 1;
for (l = 0; l < r; l++, r--) {
let temp = a[l];
a[l] = a[r];
a[r] = temp;
}
return a.join( "" );
}
function convertToBinary(n)
{
let ans= "" ;
while (n>0) {
let rem = String.fromCharCode(n % 2 + 48);
ans+=(rem);
n = parseInt(n / 2, 10);
}
ans = reverse(ans);
return ans;
}
function IsSumEqualsXorUtil(N)
{
let s = convertToBinary(N);
for (let i = 0; i < dp.length; i++)
{
for (let j = 0; j < dp[0].length; j++) {
dp[i][j] = -1;
}
}
document.write(IsSumEqualsXor(0, s.length, 1, s.split( '' )) + "</br>" );
}
let N = 10;
IsSumEqualsXorUtil(N);
</script>
|
Time Complexity: O(Log2N)
Auxiliary Space: O(Log2N)
Share your thoughts in the comments
Please Login to comment...