Open In App

Count numbers in range [L, R] having K consecutive set bits

Last Updated : 12 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given three positive integers L, R, and K, the task is to find the count of numbers in the range [L, R] having K consecutive set bits in their binary representation.

Examples:

Input: L = 4, R = 15, K = 3 
Output:
Explanation: 
Numbers whose binary representation contains K(=3) consecutive set bits are: 
(7)10 = (111)2 
(14)10 = (1110)2 
(15)10 = (1111)2 
Therefore, the required output is 3. 

Input: L = 8, R = 100, K = 3 
Output: 27

Naive Approach: The simplest approach to solve this problem to traverse all possible integers in the range [L, R] and for each number, check if binary representation of the number contains K consecutive 1s or not. If found to be true then print the number.

Time Complexity: O((R – L + 1) * 32)
Auxiliary Space: O(1)

Efficient Approach: The problem can be solved using Digit DP. The idea is to count of numbers having K consecutive 1s in the range [1, R] and subtract the count of the numbers having K consecutive 1s in the range [1, L – 1]. Following are the recurrence relations:

cntN1X(len, cntOne, KOne)                      [Tex]= \sum^{1}_{i=0} cntN1X(len + 1, cntOne + i, KOne | (cntOne == K))                     [/Tex]
 

cntN1X(len, cntOne, KOne): Stores the count of numbers in the range [1, X] with the following constraints: 
len = length of binary representation of X
cntOne = Count of consecutive 1s till index len
KOne = Boolean value to check if K consecutive 1s present in X or not. 
 


 

Follow the steps below to solve the problem:

  • Initialize a 4D array dp[len][cntOne][KOne][tight] to compute and store the values of all subproblems of the above recurrence relation.
  • Finally, return the value of dp[len][cntOne][KOne][tight].

Below is the implementation of the above approach:

C++

// C++ program to implement
// the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the count of numbers in
// range[1, X] having K consecutive set bits
int cntN1X(string str, int len, int K,
    int cntOne, int dp[32][32][2][2],
                bool KOne, bool tight)
{
    // If length of current number is
    // equal to length of string
    if (len == str.length()) {
         
        // If count of consecutive set bits
        // in the current string is >= K
        return (KOne == 1);
    }
     
    // If already computedx
    // equal occurred
    if (dp[len][cntOne][KOne][tight]
                                   != -1) {
        return dp[len][cntOne][KOne][tight];
    }
 
    // If tight is 1, then element present
    // at current index is element present
    // in str at current index. Otherwise, 1.
    int end = tight ? (str[len] - '0'): 1;
     
    // Stores count of numbers whose
    // len th bit is i.
    int res = 0;
     
    // Iterate over all possible
    // value present at current index.
    for(int i = 0; i <= end; i++) {
         
        // Stores count of consecutive 1s
        int temp = (i==1) ? (cntOne + 1): 0;
         
        // Update res.
        res += cntN1X(str, len + 1,
        K, temp, dp, (KOne | (temp == K)),
                    (tight & (i==end)));
    }
     
    return dp[len][cntOne][KOne][tight]
                                    = res;
}
 
 
// Function to find
// binary representation of N
string convertBinary(int N)
{
    // Stores binary
    // representation of N.
    string res;
     
    // Traverse each bit of N.
    while(N) {
         
        // Append current bit
        // in res
        res.push_back(N % 2 + '0');
         
        // Update N.
        N /= 2;
    }
     
    // Append 0 in binary representation
    // Of N
    while(res.length() < 32) {
        res.push_back('0');
    }
     
    // Reverse binary representation of N
    reverse(res.begin(), res.end());
     
    return res;
}
 
// Function to count numbers in
// range[L, R] having K consecutive 1s.
int cntN1XL_R(int L, int R, int K)
{
    // Stores binary representation
    // of (L - 1)
    string Ls = convertBinary(L - 1);
     
    // Stores binary representation
    // of R
    string Rs = convertBinary(R);
     
    // Stores values of overlapping
    // subproblems
    int dp[32][32][2][2];
     
    // Initialize dp[][][][] array.
    memset(dp, -1, sizeof(dp));
     
    // Stores count of numbers from
    // [1, L - 1] having K consecutive 1s
    int resL = cntN1X(Ls, 0, K, 0,
                            dp, 0,1);
     
    // Initialize dp[][][][] array.
    memset(dp, -1, sizeof(dp));
     
     
    // Stores count of numbers from
    // [1, R - 1] having K consecutive 1s
    int resR = cntN1X(Rs, 0, K, 0,
                            dp, 0, 1);
     
    // Return total counts having K
    // consecutive 1s in range[L, R]
    return (resR - resL);
}
 
// Driver Code
int main()
{
    int L = 8;
    int R = 100;
    int K = 3;
    cout<<cntN1XL_R(L, R, K);
     
}

                    

Java

// Java program to implement
// the above approach
import java.util.*;
 
class GFG{
     
// Function to find the count of numbers in
// range[1, X] having K consecutive set bits
public static int cntN1X(String str, int len, int K,
                         int cntOne, int dp[][][][],
                         int KOne, int tight)
{
     
    // If length of current number is
    // equal to length of string
    if (len == str.length())
    {
         
        // If count of consecutive set bits
        // in the current string is >= K
        return (KOne == 1) ? 1 : 0;
    }
 
    // If already computedx
    // equal occurred
    if (dp[len][cntOne][KOne][tight] != -1)
    {
        return dp[len][cntOne][KOne][tight];
    }
 
    // If tight is 1, then element present
    // at current index is element present
    // in str at current index. Otherwise, 1.
    int end = (tight == 1) ?
              (str.charAt(len) - '0') : 1;
 
    // Stores count of numbers whose
    // len th bit is i.
    int res = 0;
 
    // Iterate over all possible
    // value present at current index.
    for(int i = 0; i <= end; i++)
    {
         
        // Stores count of consecutive 1s
        int temp = (i == 1) ? (cntOne + 1) : 0;
 
        // Update res.
        res += cntN1X(str, len + 1, K, temp, dp,
                     (int)(KOne | ((temp == K) ? 1 : 0)),
                     (int)(tight & ((i == end) ? 1 : 0)));
    }
    return dp[len][cntOne][KOne][tight] = res;
}
 
// Function to count numbers in
// range[L, R] having K consecutive 1s.
public static int cntN1XL_R(int L, int R, int K)
{
     
    // Stores binary representation
    // of (L - 1)
    String Ls = Integer.toBinaryString(L - 1);
 
    // Stores binary representation
    // of R
    String Rs = Integer.toBinaryString(R);
 
    // Stores values of overlapping
    // subproblems
    int dp[][][][] = new int[32][32][2][2];
 
    // Initialize dp[][][][] array.
    for(int i[][][] : dp)
        for(int j[][] : i)
            for(int k[] : j)
                Arrays.fill(k, -1);
 
    // Stores count of numbers from
    // [1, L - 1] having K consecutive 1s
    int resL = cntN1X(Ls, 0, K, 0, dp, 0, 1);
 
    // Initialize dp[][][][] array.
    for(int i[][][] : dp)
        for(int j[][] : i)
            for(int k[] : j)
                Arrays.fill(k, -1);
 
    // Stores count of numbers from
    // [1, R - 1] having K consecutive 1s
    int resR = cntN1X(Rs, 0, K, 0, dp, 0, 1);
 
    // Return total counts having K
    // consecutive 1s in range[L, R]
    return (resR - resL);
}
 
// Driver Code
public static void main(String args[])
{
    int L = 8;
    int R = 100;
    int K = 3;
     
    System.out.println(cntN1XL_R(L, R, K));
}
}
 
// This code is contributed by hemanth gadarla

                    

Python3

# Python3 program to implement
# the above approach
  
# Function to find the count of numbers in
# range[1, X] having K consecutive set bits
def cntN1X(stri, leng, K, cntOne, dp, KOne, tight):
 
    # If length of current number is
    # equal to length of string
    if (leng == len(stri)):
          
        # If count of consecutive set bits
        # in the current string is >= K
        return 1 if (KOne == 1) else 0;
          
    # If already computedx
    # equal occurred
    if (dp[leng][cntOne][KOne][tight]  != -1):
        return dp[leng][cntOne][KOne][tight];
      
    # If tight is 1, then element present
    # at current index is element present
    # in stri at current index. Otherwise, 1.
    end = (ord(stri[leng]) - ord('0')) if tight == 1 else 1;
      
    # Stores count of numbers whose
    # leng th bit is i.
    res = 0;
      
    # Iterate over all possible
    # value present at current index.
    for i in range(end + 1):
          
        # Stores count of consecutive 1s
        temp = (cntOne + 1) if (i == 1) else 0;
          
        # Update res.
        res += cntN1X(stri, leng + 1,
        K, temp, dp, 1 if(KOne | (temp == K)) else 0,
                    1 if(tight & (i == end)) else 0);
     
    dp[leng][cntOne][KOne][tight]= res
    return res
  
# Function to find
# binary representation of N
def convertBinary(N):
 
    # Stores binary
    # representation of N.
    res=''
      
    # Traverse each bit of N.
    while(N != 0):
          
        # Append current bit
        # in res
        res += chr((N % 2) + ord('0'));
          
        # Update N.
        N //= 2;
         
    # Append 0 in binary representation
    # Of N
    while(len(res) < 32):
        res += '0';
          
    # Reverse binary representation of N
    return res[::-1];
 
# Function to count numbers in
# range[L, R] having K consecutive 1s.
def cntN1XL_R(L, R, K):
 
    # Stores binary representation
    # of (L - 1)
    Ls = str(convertBinary(L - 1));
      
    # Stores binary representation
    # of R
    Rs = str(convertBinary(R));
      
    # Stores values of overlapping
    # subproblems
    dp =[[[[-1,-1] for j in range(2)] for k in range(32)] for l in range(32)]
      
    # Stores count of numbers from
    # [1, L - 1] having K consecutive 1s
    resL = cntN1X(Ls, 0, K, 0, dp, 0,1);
          
    # Initialize dp[][][][] array.
    dp = [[[[-1, -1] for j in range(2)] for k in range(32)] for l in range(32)]
          
    # Stores count of numbers from
    # [1, R - 1] having K consecutive 1s
    resR = cntN1X(Rs, 0, K, 0,
                            dp, 0, 1);
      
    # Return total counts having K
    # consecutive 1s in range[L, R]
    return (resR - resL);
  
# Driver Code
if __name__=='__main__':
     
    L = 8;
    R = 100;
    K = 3;
    print(cntN1XL_R(L, R, K))
     
# This code is contributed by rutvik_56

                    

C#

// C# program to implement
// the above approach
using System;
 
class GFG{
     
// Function to find the count of numbers in
// range[1, X] having K consecutive set bits
public static int cntN1X(String str, int len, int K,
                         int cntOne, int [,,,]dp,
                         int KOne, int tight)
{
     
    // If length of current number is
    // equal to length of string
    if (len == str.Length)
    {
         
        // If count of consecutive set bits
        // in the current string is >= K
        return (KOne == 1) ? 1 : 0;
    }
     
    // If already computedx
    // equal occurred
    if (dp[len, cntOne, KOne, tight] != -1)
    {
        return dp[len, cntOne, KOne, tight];
    }
     
    // If tight is 1, then element present
    // at current index is element present
    // in str at current index. Otherwise, 1.
    int end = (tight == 1) ?
              (str[len] - '0') : 1;
 
    // Stores count of numbers whose
    // len th bit is i.
    int res = 0;
 
    // Iterate over all possible
    // value present at current index.
    for(int i = 0; i <= end; i++)
    {
         
        // Stores count of consecutive 1s
        int temp = (i == 1) ? (cntOne + 1) : 0;
 
        // Update res.
        res += cntN1X(str, len + 1, K, temp, dp,
                     (int)(KOne | ((temp == K) ? 1 : 0)),
                     (int)(tight & ((i == end) ? 1 : 0)));
    }
    return dp[len, cntOne, KOne, tight] = res;
}
 
// Function to count numbers in
// range[L, R] having K consecutive 1s.
public static int cntN1XL_R(int L, int R, int K)
{
     
    // Stores binary representation
    // of (L - 1)
    String Ls = Convert.ToString(L - 1, 2);
 
    // Stores binary representation
    // of R
    String Rs = Convert.ToString(R, 2);
 
    // Stores values of overlapping
    // subproblems
    int [,,,]dp = new int[ 32, 32, 2, 2 ];
 
    // Initialize [,]dp[,] array.
    for(int i = 0; i < 32; i++)
        for(int j = 0; j < 32; j++)
            for(int k = 0; k < 2; k++)
                for(int l = 0; l < 2; l++)
                    dp[i, j, k, l] = -1;
                     
    // Stores count of numbers from
    // [1, L - 1] having K consecutive 1s
    int resL = cntN1X(Ls, 0, K, 0, dp, 0, 1);
     
    // Initialize [,]dp[,] array.
    for(int i = 0; i < 32; i++)
        for(int j = 0; j < 32; j++)
            for(int k = 0; k < 2; k++)
                for(int l = 0; l < 2; l++)
                    dp[i, j, k, l] = -1;
                     
    // Stores count of numbers from
    // [1, R - 1] having K consecutive 1s
    int resR = cntN1X(Rs, 0, K, 0, dp, 0, 1);
     
    // Return total counts having K
    // consecutive 1s in range[L, R]
    return (resR - resL);
}
 
// Driver Code
public static void Main(String []args)
{
    int L = 8;
    int R = 100;
    int K = 3;
     
    Console.WriteLine(cntN1XL_R(L, R, K));
}
}
 
// This code is contributed by gauravrajput1

                    

Javascript

<script>
 
    // JavaScript program to implement the above approach
     
    // Function to find the count of numbers in
    // range[1, X] having K consecutive set bits
    function cntN1X(str, len, K, cntOne, dp, KOne, tight)
    {
 
        // If length of current number is
        // equal to length of string
        if (len == str.length)
        {
 
            // If count of consecutive set bits
            // in the current string is >= K
            return (KOne == 1) ? 1 : 0;
        }
 
        // If already computedx
        // equal occurred
        if (dp[len][cntOne][KOne][tight] != -1)
        {
            return dp[len][cntOne][KOne][tight];
        }
 
        // If tight is 1, then element present
        // at current index is element present
        // in str at current index. Otherwise, 1.
        let end = (tight == 1) ?
                  (str[len].charCodeAt()- '0'.charCodeAt()) : 1;
 
        // Stores count of numbers whose
        // len th bit is i.
        let res = 0;
 
        // Iterate over all possible
        // value present at current index.
        for(let i = 0; i <= end; i++)
        {
 
            // Stores count of consecutive 1s
            let temp = (i == 1) ? (cntOne + 1) : 0;
 
            // Update res.
            res += cntN1X(str, len + 1, K, temp, dp,
                         (KOne | ((temp == K) ? 1 : 0)),
                         (tight & ((i == end) ? 1 : 0)));
        }
        dp[len][cntOne][KOne][tight] = res;
        return dp[len][cntOne][KOne][tight];
    }
     
    // Function to count numbers in
    // range[L, R] having K consecutive 1s.
    function cntN1XL_R(L, R, K)
    {
 
        // Stores binary representation
        // of (L - 1)
        let Ls = (L - 1).toString(2);
 
        // Stores binary representation
        // of R
        let Rs = (R).toString(2);
 
        // Stores values of overlapping
        // subproblems
        let dp = new Array(32);
 
        // Initialize dp[][][][] array.
        for(let i = 0; i < 32; i++)
        {
            dp[i] = new Array(32);
            for(let j = 0; j < 32; j++)
            {
                dp[i][j] = new Array(2);
                for(let k = 0; k < 2; k++)
                {
                    dp[i][j][k] = new Array(2);
                    for(let l = 0; l < 2; l++)
                    {
                        dp[i][j][k][l] = -1;
                    }
                }
            }
        }
 
        // Stores count of numbers from
        // [1, L - 1] having K consecutive 1s
        let resL = cntN1X(Ls, 0, K, 0, dp, 0, 1);
 
        // Initialize dp[][][][] array.
        for(let i = 0; i < 32; i++)
        {
            dp[i] = new Array(32);
            for(let j = 0; j < 32; j++)
            {
                dp[i][j] = new Array(2);
                for(let k = 0; k < 2; k++)
                {
                    dp[i][j][k] = new Array(2);
                    for(let l = 0; l < 2; l++)
                    {
                        dp[i][j][k][l] = -1;
                    }
                }
            }
        }
 
        // Stores count of numbers from
        // [1, R - 1] having K consecutive 1s
        let resR = cntN1X(Rs, 0, K, 0, dp, 0, 1);
 
        // Return total counts having K
        // consecutive 1s in range[L, R]
        return (resR - resL);
    }
     
    let L = 8;
    let R = 100;
    let K = 3;
      
    document.write(cntN1XL_R(L, R, K));
 
</script>

                    

Output
27

Time complexity: O(32K(log(R) + log(L))), where K is the number of consecutive set bits and log(R) and log(L) represent the maximum number of bits in binary representation of R and L, respectively
Auxiliary Space: O(32K2*2)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads