Open In App

Find numbers in the range L to R whose bitwise OR of digits is exactly K

Improve
Improve
Like Article
Like
Save
Share
Report

Given integers L and R, the task is to find the number of integers in the range L to R whose bitwise OR of digits is exactly K. Print the answer.

Examples:

Input: L = 1, R = 15, K =5 
Output: 3
Explanation: 

Total three numbers 5, 14 and 15 are there whose bitwise OR of digits is exactly K = 5 

Input: L = 1, R = 100, K = 5
Output: 9

Naive approach: The basic way to solve the problem is as follows:

The basic way to solve this problem is to generate all possible combinations by using a recursive approach.

Time Complexity: O(N10)
Auxiliary Space: O(1)

Efficient Approach:  The above approach can be optimized based on the following idea:

Dynamic programming can be used to solve this problem:

  • dp[i][j][k] represents numbers in the range with i digits, j represents the tight condition and k represents the current bitwise OR sum.
  • It can be observed that the recursive function is called exponential times. 
  • That means that some states are called repeatedly. So the idea is to store the value of each state. This can be done using by the store the value of a state and whenever the function is called, returning the stored value without computing again.
  • The first answer will be calculated for 0 to L – 1 and then calculated for 0 to R then the latter one is subtracted from the prior one to get an answer for range [L, R]

Follow the steps below to solve the problem:

  • Create a recursive function that takes three parameters i representing position to be filled, j representing tight condition, and k representing bitwise OR sum of digits.
  • Call the recursive function for choosing all digits from 0 to 9.
  • In the base case, if the size of the digit is N and bitwise OR sum is K return 1 otherwise return 0.
  • Create a 3d array  dp[100001][2][16] initially filled with -1.
  • If the answer for a particular state is computed then save it in dp[i][j][k].
  • if the answer for a particular state is already computed then just return dp[i][j][k].

Below is the implementation of the above approach:

C++14




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// DP table initialized with -1
int dp[100001][2][16];
 
// Recursive Function to find numbers
// in the range L to R such that its
// bitwise OR is K.
int recur(int i, int j, int k, int T, string& a)
{
    // Base case
    if (i == a.size()) {
 
        // If bitwise OR is K
        if (k == T)
            return 1;
 
        // Otherwise return 0
        else
            return 0;
    }
 
    // If answer for current state is
    // already calculated then just
    // return dp[i][j][k]
    if (dp[i][j][k] != -1)
        return dp[i][j][k];
 
    // Answer initialized with zero
    int ans = 0;
 
    // Tight condition true
    if (j == 1) {
 
        // Iterating from 0 to max value
        // of tight condition
        for (int digit = 0; digit <= ((int)a[i] - 48);
             digit++) {
 
            // When digit is at max tight
            // condition remains even
            // in next state
            if (digit == ((int)a[i] - 48))
 
                // Calling recursive function
                // for tight digit
                ans += recur(i + 1, 1, k | digit, T, a);
 
            // Tight condition drops
            else if (digit != 0)
 
                // Calling recursive function
                // for digits less than tight
                // condition digit
                ans += recur(i + 1, 0, k | digit, T, a);
 
            else
                // Calling recursive
                // function for 0
                ans += recur(i + 1, 0, k | digit, T, a);
        }
    }
 
    // Tight condition false
    else {
 
        // Iterating for all digits
        for (int digit = 0; digit <= 9; digit++) {
 
            // Calling recursive function
            // for all digits from 0 to 9
            ans += recur(i + 1, 0, k | digit, T, a);
        }
    }
 
    // Save and return dp value
    return dp[i][j][k] = ans;
}
 
// Function to find numbers
// in the range L to R such that its
// bitwise OR is K.
int countInRange(int K, int A, int B)
{
 
    // Initializing dp array with - 1
    memset(dp, -1, sizeof(dp));
 
    A--;
    string L = to_string(A), R = to_string(B);
 
    // Numbers with bitwise OR sum of
    // digits K in the range 0 to L
    int ans1 = recur(0, 1, 0, K, L);
 
    // Initializing dp array with - 1
    memset(dp, -1, sizeof(dp));
 
    // Numbers with bitwise OR sum of
    // digits K in the range 0 to R
    int ans2 = recur(0, 1, 0, K, R);
 
    // Difference of ans2 and ans1
    // will generate answer for
    // required range
    return ans2 - ans1;
}
 
// Driver Code
int main()
{
    // Input 1
    int L = 1, R = 20, K = 5;
 
    // Function Call
    cout << countInRange(K, L, R) << endl;
 
    // Input 2
    int L1 = 1, R1 = 100, K1 = 5;
 
    // Function Call
    cout << countInRange(K1, L1, R1) << endl;
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
import java.util.*;
 
class GFG {
 
  // DP table initialized with -1
  static int[][][] dp = new int[100001][2][16];
 
  // Recursive Function to find numbers
  // in the range L to R such that its
  // bitwise OR is K.
  static int recur(int i, int j, int k, int T, String a)
  {
     
    // Base case
    if (i == a.length())
    {
       
      // If bitwise OR is K
      if (k == T) {
        return 1;
      }
       
      // Otherwise return 0
      else {
        return 0;
      }
    }
    // If answer for current state is
    // already calculated then just
    // return dp[i][j][k]
    if (dp[i][j][k] != -1) {
      return dp[i][j][k];
    }
     
    // Answer initialized with zero
    int ans = 0;
     
    // Tight condition true
    if (j == 1)
    {
       
      // Iterating from 0 to max value
      // of tight condition
      for (int digit = 0;
           digit <= (a.charAt(i) - '0'); digit++)
      {
         
        // When digit is at max tight
        // condition remains even
        // in next state
        if (digit == (a.charAt(i) - '0'))
        {
           
          // Calling recursive function
          // for tight digit
          ans += recur(i + 1, 1, k | digit, T, a);
        }
         
        // Tight condition drops
        else if (digit != 0)
        {
           
          // Calling recursive function
          // for digits less than tight
          // condition digit
          ans += recur(i + 1, 0, k | digit, T, a);
        }
        else
        {
           
          // Calling recursive
          // function for 0
          ans += recur(i + 1, 0, k | digit, T, a);
        }
      }
    }
     
    // Tight condition false
    else
    {
       
      // Iterating for all digits
      for (int digit = 0; digit <= 9; digit++)
      {
         
        // Calling recursive function
        // for all digits from 0 to 9
        ans += recur(i + 1, 0, k | digit, T, a);
      }
    }
     
    // Save and return dp value
    return dp[i][j][k] = ans;
  }
 
  // Function to find numbers
  // in the range L to R such that its
  // bitwise OR is K.
  static int countInRange(int K, int A, int B)
  {
     
    // Initializing dp array with - 1
    for (int[][] dp1 : dp) {
      for (int[] dp11 : dp1) {
        Arrays.fill(dp11, -1);
      }
    }
    A--;
    String L = Integer.toString(A),
    R = Integer.toString(B);
     
    // Numbers with bitwise OR sum of
    // digits K in the range 0 to L
    int ans1 = recur(0, 1, 0, K, L);
     
    // Initializing dp array with - 1
    for (int[][] dp1 : dp) {
      for (int[] dp11 : dp1) {
        Arrays.fill(dp11, -1);
      }
    }
     
    // Numbers with bitwise OR sum of
    // digits K in the range 0 to R
    int ans2 = recur(0, 1, 0, K, R);
     
    // Difference of ans2 and ans1
    // will generate answer for
    // required range
    return ans2 - ans1;
  }
 
  public static void main(String[] args)
  {
     
    // Input 1
    int L = 1, R = 20, K = 5;
     
    // Function Call
    System.out.println(countInRange(K, L, R));
     
    // Input 2
    int L1 = 1, R1 = 100, K1 = 5;
     
    // Function Call
    System.out.println(countInRange(K1, L1, R1));
  }
}
 
// This code is contributed by lokesh.


Python3




# Python3 code to implement the approach
 
# DP table initialized with -1
dp = [[[-1 for _ in range(16)] for _ in range(2)] for _ in range(100001)]
 
# Recursive Function to find numbers
# in the range L to R such that its
# bitwise OR is K.
def recur(i, j, k, T, a):
    # Base case
    if i == len(a):
        # If bitwise OR is K
        if k == T:
            return 1
        # Otherwise return 0
        else:
            return 0
 
    # If answer for current state is
    # already calculated then just
    # return dp[i][j][k]
    if dp[i][j][k] != -1:
        return dp[i][j][k]
 
    # Answer initialized with zero
    ans = 0
 
    # Tight condition true
    if j == 1:
        # Iterating from 0 to max value
        # of tight condition
        for digit in range(int(a[i])+1 if int(a[i]) < 9 else 10):
            # When digit is at max tight
            # condition remains even
            # in next state
            if digit == int(a[i]):
                # Calling recursive function
                # for tight digit
                ans += recur(i + 1, 1, k | digit, T, a)
            # Tight condition drops
            elif digit != 0:
                # Calling recursive function
                # for digits less than tight
                # condition digit
                ans += recur(i + 1, 0, k | digit, T, a)
            else:
                # Calling recursive
                # function for 0
                ans += recur(i + 1, 0, k | digit, T, a)
 
    # Tight condition false
    else:
        # Iterating for all digits
        for digit in range(10):
            # Calling recursive function
            # for all digits from 0 to 9
            ans += recur(i + 1, 0, k | digit, T, a)
 
    # Save and return dp value
    dp[i][j][k] = ans
    return ans
 
# Function to find numbers
# in the range L to R such that its
# bitwise OR is K.
def countInRange(K, A, B):
    # Initializing dp array with - 1
    global dp
    dp = [[[-1 for _ in range(16)] for _ in range(2)] for _ in range(100001)]
 
    A -= 1
    L = str(A)
    R = str(B)
 
    # Numbers with bitwise OR sum of
    # digits K in the range 0 to L
    ans1 = recur(0, 1, 0, K, L)
 
    # Initializing dp array with - 1
    dp = [[[-1 for _ in range(16)] for _ in range(2)] for _ in range(100001)]
 
    # Numbers with bitwise OR sum of
    # digits K in the range 0 to R
    ans2 = recur(0, 1, 0, K, R)
 
    # Difference of ans2 and ans1
    # will generate answer for
    # required range
    return ans2-ans1
 
# Driver code
def main():
    L = 1
    R = 20
    K = 5
 
    print(countInRange(K, L, R))
 
    L1 = 1
    R1 = 100
    K1 = 5
 
    print(countInRange(K1, L1, R1))
 
if __name__ == "__main__":
    main()
 
    # This code is contributed by unstoppablepandu.


C#




// C# code to implement the approach
using System;
public class GFG {
 
  // DP table initialized with -1
  static int[, , ] dp = new int[100001, 2, 16];
 
  // Recursive Function to find numbers
  // in the range L to R such that its
  // bitwise OR is K.
  static int recur(int i, int j, int k, int T, string a)
  {
 
    // Base case
    if (i == a.Length)
    {
 
      // If bitwise OR is K
      if (k == T) {
        return 1;
      }
      // Otherwise return 0
      else {
        return 0;
      }
    }
 
    // If answer for current state is
    // already calculated then just
    // return dp[i][j][k]
    if (dp[i, j, k] != -1) {
      return dp[i, j, k];
    }
 
    // Answer initialized with zero
    int ans = 0;
 
    // Tight condition true
    if (j == 1)
    {
 
      // Iterating from 0 to max value
      // of tight condition
      for (int digit = 0; digit <= (a[i] - '0');
           digit++)
      {
 
        // When digit is at max tight
        // condition remains even
        // in next state
        if (digit == (a[i] - '0'))
        {
 
          // Calling recursive function
          // for tight digit
          ans += recur(i + 1, 1, k | digit, T, a);
        }
 
        // Tight condition drops
        else if (digit != 0)
        {
 
          // Calling recursive function
          // for digits less than tight
          // condition digit
          ans += recur(i + 1, 0, k | digit, T, a);
        }
        else
        {
 
          // Calling recursive
          // function for 0
          ans += recur(i + 1, 0, k | digit, T, a);
        }
      }
    }
    // Tight condition false
    else {
      // Iterating for all digits
      for (int digit = 0; digit <= 9; digit++) {
        // Calling recursive function
        // for all digits from 0 to 9
        ans += recur(i + 1, 0, k | digit, T, a);
      }
    }
 
    // Save and return dp value
    return dp[i, j, k] = ans;
  }
 
  // Function to find numbers
  // in the range L to R such that its
  // bitwise OR is K.
  static int countInRange(int K, int A, int B)
  {
    // Initializing dp array with - 1
    for (int i = 0; i < dp.GetLength(0); i++) {
      for (int j = 0; j < dp.GetLength(1); j++) {
        for (int k = 0; k < dp.GetLength(2); k++) {
          dp[i, j, k] = -1;
        }
      }
    }
    A--;
    string L = A.ToString();
    string R = B.ToString();
 
    // Numbers with bitwise OR sum of
    // digits K in the range 0 to L
    int ans1 = recur(0, 1, 0, K, L);
 
    // Initializing dp array with - 1
    for (int i = 0; i < dp.GetLength(0); i++) {
      for (int j = 0; j < dp.GetLength(1); j++) {
        for (int k = 0; k < dp.GetLength(2); k++) {
          dp[i, j, k] = -1;
        }
      }
    }
 
    // Numbers with bitwise OR sum of
    // digits K in the range 0 to R
    int ans2 = recur(0, 1, 0, K, R);
 
    // Difference of ans2 and ans1
    // will generate answer for
    // required range
    return ans2 - ans1;
  }
 
  static public void Main()
  {
 
    // Code
    // Input 1
    int L = 1, R = 20, K = 5;
 
    // Function Call
    Console.WriteLine(countInRange(K, L, R));
 
    // Input 2
    int L1 = 1, R1 = 100, K1 = 5;
 
    // Function Call
    Console.WriteLine(countInRange(K1, L1, R1));
  }
}
 
// This code is contributed by lokeshmvs21.


Javascript




let dp = Array.from({ length: 100001 }, () => Array.from({ length: 2 }, () => Array.from({ length: 16 }, () => -1)));
 
function recur(i, j, k, T, a) {
    // Base case
    if (i == a.length) {
        // If bitwise OR is K
        if (k == T) {
            return 1;
        }
        // Otherwise return 0
        else {
            return 0;
        }
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j][k]
    if (dp[i][j][k] != -1) {
        return dp[i][j][k];
    }
 
    // Answer initialized with zero
    let ans = 0;
 
    // Tight condition true
    if (j == 1) {
        // Iterating from 0 to max value of tight condition
        for (let digit = 0; digit <= (parseInt(a[i]) < 9 ? parseInt(a[i]) : 9); digit++) {
            // When digit is at max tight condition remains even in next state
            if (digit == parseInt(a[i])) {
                // Calling recursive function for tight digit
                ans += recur(i + 1, 1, k | digit, T, a);
            }
            // Tight condition drops for digits less than tight condition digit
            else if (digit != 0) {
                // Calling recursive function for digits less than tight condition digit
                ans += recur(i + 1, 0, k | digit, T, a);
            }
            else {
                // Calling recursive function for 0
                ans += recur(i + 1, 0, k | digit, T, a);
            }
        }
    }
    // Tight condition false
    else {
        // Iterating for all digits
        for (let digit = 0; digit <= 9; digit++)
        {
         
            // Calling recursive function for all digits from 0 to 9
            ans += recur(i + 1, 0, k | digit, T, a);
        }
    }
 
    // Save and return dp value
    dp[i][j][k] = ans;
    return ans;
}
 
function countInRange(K, A, B) {
    // Initializing dp array with -1
    dp = Array.from({ length: 100001 }, () => Array.from({ length: 2 }, () => Array.from({ length: 16 }, () => -1)));
 
    A -= 1;
    let L = A.toString();
    let R = B.toString();
 
    // Numbers with bitwise OR sum of digits K in the range 0 to L
    let ans1 = recur(0, 1, 0, K, L);
 
    // Initializing dp array with -1
    dp = Array.from({ length: 100001 }, () => Array.from({ length: 2 }, () => Array.from({ length: 16 }, () => -1)));
 
    // Numbers with bitwise OR sum of digits K in the range 0 to R
    let ans2 = recur(0, 1, 0, K, R);
 
    // Difference of ans2 and ans1 will generate answer for required range
    return ans2 - ans1;
}
 
// Driver code
 
    let L = 1;
    let R = 20;
    let K = 5;
    console.log(countInRange(K, L, R));
 
    let L1 = 1;
    let R1 = 100;
    let K1 = 5;
     
 console.log(countInRange(K1, L1, R1));


Output

3
9

Time Complexity: O(log(R – L))  
Auxiliary Space: O(log(R – L))

Related Articles:



Last Updated : 21 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads