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:
- For number 5 its bitwise OR of digits will be 5
- For number 14 its bitwise OR of digits will be 5
- for number 15 its bitwise OR of digits will be 5
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++ 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 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 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# 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. |
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));
|
3 9
Time Complexity: O(log(R – L))
Auxiliary Space: O(log(R – L))
Related Articles: