Open In App

Count of integers of length N and value less than K such that they contain digits only from the given set

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given a set of digits A[] in sorted order and two integers N and K, the task is to find how many numbers of length N are possible whose value is less than K and the digits are from the given set only. Note that you can use the same digit multiple times.

Examples: 

Input: A[] = {0, 1, 5}, N = 1, K = 2 
Output:
Only valid numbers are 0 and 1.

Input: A[] = {0, 1, 2, 5}, N = 2, K = 21 
Output:
10, 11, 12, 15 and 20 are the valid numbers. 
 

Approach: Let d be the size of A[]. We can break this problem into three simpler cases.  

  1. When N is greater than the length of K, It is obvious that if the length of N is greater than the length of k or if d is equal to 0, no such number is possible.
  2. When N is smaller than the length of K, then all possible combinations of digit of length N are valid. Also, we have to keep in mind that 0 can’t be in the first place. So, if A[] contains 0, the first place can be filled in (d – 1) ways. Since repetition is allowed and 0 can occupy the other places, rest N – 1 places can be filled in d * d * … * d(N – 1) times i.e. in dN – 1 ways. Therefore the answer is (d – 1) * (dN – 1) if A[] contains 0 else dN.
  3. When N is equal to the length of K, this is the trickiest part. We need to use Dynamic Programming for this part. Construct a digit array of K. Let’s call it digit[]. Let First(i) be the number formed by taking the first i digits of it. Let lower[i] denote the number of elements in A[] which are smaller than i
    For example, First(2) of 423 is 42. If A[] = {0, 2} then lower[0] = 0, lower[1] = 1, lower[2] = 1, lower[3] = 2. 
    Generate N digit numbers by dynamic programming. Let dp[i] denote total numbers of length i which are less than first i digits of K
    Elements in dp[i] can be generated by two cases: 
    • For all the numbers whose First(i – 1) is less than First(i – 1) of K, we can put any digit at ith index. Hence, dp[i] = dp[i] + (dp[i – 1] * d)
    • For all the numbers whose First(i – 1) is the same as First(i – 1) of K, we can only put those digits which are smaller than digit[i]. Hence, dp[i] = dp[i] + lower[digit[i]].

Below is the implementation of the above approach:  

C++14




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
#define MAX 10
 
// Function to convert a number into vector
vector<int> numToVec(int N)
{
    vector<int> digit;
 
    // Push all the digits of N from the end
    // one by one to the vector
    while (N != 0) {
        digit.push_back(N % 10);
        N = N / 10;
    }
 
    // If the original number was 0
    if (digit.size() == 0)
        digit.push_back(0);
 
    // Reverse the vector elements
    reverse(digit.begin(), digit.end());
 
    // Return the required vector
    return digit;
}
 
// Function to return the count of B length integers
// which are less than C and they
// contain digits from set A[] only
int solve(vector<int>& A, int B, int C)
{
    vector<int> digit;
    int d, d2;
 
    // Convert number to digit array
    digit = numToVec(C);
    d = A.size();
 
    // Case 1: No such number possible as the
    // generated numbers will always
    // be greater than C
    if (B > digit.size() || d == 0)
        return 0;
 
    // Case 2: All integers of length B are valid
    // as they all are less than C
    else if (B < digit.size()) {
        // contain 0
        if (A[0] == 0 && B != 1)
            return (d - 1) * pow(d, B - 1);
        else
            return pow(d, B);
    }
 
    // Case 3
    else {
        int dp[B + 1] = { 0 };
        int lower[MAX + 1] = { 0 };
 
        // Update the lower[] array such that
        // lower[i] stores the count of elements
        // in A[] which are less than i
        for (int i = 0; i < d; i++)
            lower[A[i] + 1] = 1;
        for (int i = 1; i <= MAX; i++)
            lower[i] = lower[i - 1] + lower[i];
 
        bool flag = true;
        dp[0] = 0;
        for (int i = 1; i <= B; i++) {
            d2 = lower[digit[i - 1]];
            dp[i] = dp[i - 1] * d;
 
            // For first index we can't use 0
            if (i == 1 && A[0] == 0 && B != 1)
                d2 = d2 - 1;
 
            // Whether (i-1) digit of generated number
            // can be equal to (i - 1) digit of C
            if (flag)
                dp[i] += d2;
 
            // Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit[i - 1] + 1]
                            == lower[digit[i - 1]] + 1));
        }
        return dp[B];
    }
}
 
// Driver code
int main()
{
 
    // Digits array
    vector<int> A = { 0, 1, 2, 5 };
    int N = 2;
    int k = 21;
 
    cout << solve(A, N, k);
 
    return 0;
}


Java




// Java implementation of the approach
import java.util.*;
 
class GFG
{
static int MAX = 10;
 
// Function to convert a number into vector
static Vector<Integer> numToVec(int N)
{
    Vector<Integer> digit = new Vector<Integer>();
 
    // Push all the digits of N from the end
    // one by one to the vector
    while (N != 0)
    {
        digit.add(N % 10);
        N = N / 10;
    }
 
    // If the original number was 0
    if (digit.size() == 0)
        digit.add(0);
 
    // Reverse the vector elements
    Collections.reverse(digit);
 
    // Return the required vector
    return digit;
}
 
// Function to return the count
// of B length integers which are
// less than C and they contain
// digits from set A[] only
static int solve(Vector<Integer> A, int B, int C)
{
    Vector<Integer> digit = new Vector<Integer>();
    int d, d2;
 
    // Convert number to digit array
    digit = numToVec(C);
    d = A.size();
 
    // Case 1: No such number possible as the
    // generated numbers will always
    // be greater than C
    if (B > digit.size() || d == 0)
        return 0;
 
    // Case 2: All integers of length B are valid
    // as they all are less than C
    else if (B < digit.size())
    {
        // contain 0
        if (A.get(0) == 0 && B != 1)
            return (int) ((d - 1) * Math.pow(d, B - 1));
        else
            return (int) Math.pow(d, B);
    }
 
    // Case 3
    else
    {
        int []dp = new int[B + 1];
        int []lower = new int[MAX + 1];
 
        // Update the lower[] array such that
        // lower[i] stores the count of elements
        // in A[] which are less than i
        for (int i = 0; i < d; i++)
            lower[A.get(i) + 1] = 1;
        for (int i = 1; i <= MAX; i++)
            lower[i] = lower[i - 1] + lower[i];
 
        boolean flag = true;
        dp[0] = 0;
        for (int i = 1; i <= B; i++)
        {
            d2 = lower[digit.get(i - 1)];
            dp[i] = dp[i - 1] * d;
 
            // For first index we can't use 0
            if (i == 1 && A.get(0) == 0 && B != 1)
                d2 = d2 - 1;
 
            // Whether (i-1) digit of generated number
            // can be equal to (i - 1) digit of C
            if (flag)
                dp[i] += d2;
 
            // Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit.get(i - 1) + 1] ==
                            lower[digit.get(i - 1)] + 1));
        }
        return dp[B];
    }
}
 
// Driver code
public static void main(String[] args)
{
    Integer arr[] = { 0, 1, 2, 5 };
    // Digits array
    Vector<Integer> A = new Vector<>(Arrays.asList(arr));
    int N = 2;
    int k = 21;
 
    System.out.println(solve(A, N, k));
}
}
 
// This code is contributed
// by PrinciRaj1992


Python3




# Python3 implementation of the approach
MAX=10
 
# Function to convert a number into vector
def numToVec(N):
     
    digit = []
 
    # Push all the digits of N from the end
    # one by one to the vector
    while (N != 0):
        digit.append(N % 10)
        N = N // 10
 
    # If the original number was 0
    if (len(digit) == 0):
        digit.append(0)
 
    # Reverse the vector elements
    digit = digit[::-1]
 
    # Return the required vector
    return digit
 
 
# Function to return the count of B length integers
# which are less than C and they
# contain digits from set A[] only
def solve(A, B, C):
    d, d2 = 0,0
 
    # Convert number to digit array
    digit = numToVec(C)
    d = len(A)
 
    # Case 1: No such number possible as the
    # generated numbers will always
    # be greater than C
    if (B > len(digit) or d == 0):
        return 0
 
    # Case 2: All integers of length B are valid
    # as they all are less than C
    elif (B < len(digit)):
        # contain 0
        if (A[0] == 0 and B != 1):
            return (d - 1) * pow(d, B - 1)
        else:
            return pow(d, B)
 
    # Case 3
    else :
        dp=[0 for i in range(B + 1)]
        lower=[0 for i in range(MAX + 1)]
 
        # Update the lower[] array such that
        # lower[i] stores the count of elements
        # in A[] which are less than i
        for i in range(d):
            lower[A[i] + 1] = 1
        for i in range(1, MAX+1):
            lower[i] = lower[i - 1] + lower[i]
 
        flag = True
        dp[0] = 0
        for i in range(1, B+1):
            d2 = lower[digit[i - 1]]
            dp[i] = dp[i - 1] * d
 
            # For first index we can't use 0
            if (i == 1 and A[0] == 0 and B != 1):
                d2 = d2 - 1
 
            # Whether (i-1) digit of generated number
            # can be equal to (i - 1) digit of C
            if (flag):
                dp[i] += d2
 
            # Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit[i - 1] + 1] == lower[digit[i - 1]] + 1))
         
        return dp[B]
 
# Driver code
 
# Digits array
A =[0, 1, 2, 5]
N = 2
k = 21
 
print(solve(A, N, k))
 
# This code is contributed by mohit kumar 29


C#




// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GFG
{
static int MAX = 10;
 
// Function to convert a number into vector
static List<int> numToVec(int N)
{
    List<int> digit = new List<int>();
 
    // Push all the digits of N from the end
    // one by one to the vector
    while (N != 0)
    {
        digit.Add(N % 10);
        N = N / 10;
    }
 
    // If the original number was 0
    if (digit.Count == 0)
        digit.Add(0);
 
    // Reverse the vector elements
    digit.Reverse();
 
    // Return the required vector
    return digit;
}
 
// Function to return the count
// of B length integers which are
// less than C and they contain
// digits from set A[] only
static int solve(List<int> A, int B, int C)
{
    List<int> digit = new List<int>();
    int d, d2;
 
    // Convert number to digit array
    digit = numToVec(C);
    d = A.Count;
 
    // Case 1: No such number possible as the
    // generated numbers will always
    // be greater than C
    if (B > digit.Count || d == 0)
        return 0;
 
    // Case 2: All integers of length B are valid
    // as they all are less than C
    else if (B < digit.Count)
    {
        // contain 0
        if (A[0] == 0 && B != 1)
            return (int) ((d - 1) * Math.Pow(d, B - 1));
        else
            return (int) Math.Pow(d, B);
    }
 
    // Case 3
    else
    {
        int []dp = new int[B + 1];
        int []lower = new int[MAX + 1];
 
        // Update the lower[] array such that
        // lower[i] stores the count of elements
        // in A[] which are less than i
        for (int i = 0; i < d; i++)
            lower[A[i] + 1] = 1;
        for (int i = 1; i <= MAX; i++)
            lower[i] = lower[i - 1] + lower[i];
 
        Boolean flag = true;
        dp[0] = 0;
        for (int i = 1; i <= B; i++)
        {
            d2 = lower[digit[i-1]];
            dp[i] = dp[i - 1] * d;
 
            // For first index we can't use 0
            if (i == 1 && A[0] == 0 && B != 1)
                d2 = d2 - 1;
 
            // Whether (i-1) digit of generated number
            // can be equal to (i - 1) digit of C
            if (flag)
                dp[i] += d2;
 
            // Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit[i-1] + 1] ==
                            lower[digit[i-1]] + 1));
        }
        return dp[B];
    }
}
 
// Driver code
public static void Main(String[] args)
{
    int []arr = { 0, 1, 2, 5 };
     
    // Digits array
    List<int> A = new List<int>(arr);
    int N = 2;
    int k = 21;
 
    Console.WriteLine(solve(A, N, k));
}
}
 
// This code is contributed by Rajput-Ji


Javascript




<script>
 
// Javascript implementation of the approach
let MAX = 10;
 
// Function to convert a number into vector
function numToVec(N)
{
    let digit = [];
         
    // Push all the digits of N from the end
    // one by one to the vector
    while (N != 0)
    {
        digit.push(N % 10);
        N = Math.floor(N / 10);
    }
   
    // If the original number was 0
    if (digit.length == 0)
        digit.push(0);
   
    // Reverse the vector elements
    digit.reverse();
   
    // Return the required vector
    return digit;
}
 
// Function to return the count
// of B length integers which are
// less than C and they contain
// digits from set A[] only
function solve(A, B, C)
{
    let digit = [];
    let d, d2;
   
    // Convert number to digit array
    digit = numToVec(C);
    d = A.length;
   
    // Case 1: No such number possible as the
    // generated numbers will always
    // be greater than C
    if (B > digit.length || d == 0)
        return 0;
   
    // Case 2: All integers of length B are valid
    // as they all are less than C
    else if (B < digit.length)
    {
         
        // contain 0
        if (A[0] == 0 && B != 1)
            return  Math.floor((d - 1) *
                    Math.pow(d, B - 1));
        else
            return Math.floor(Math.pow(d, B));
    }
   
    // Case 3
    else
    {
        let dp = new Array(B + 1);
        let lower = new Array(MAX + 1);
         
          for(let i = 0; i < dp.length; i++)
        {
            dp[i] = 0;
        }
        for(let i = 0; i < lower.length; i++)
        {
            lower[i] = 0;
        }
         
        // Update the lower[] array such that
        // lower[i] stores the count of elements
        // in A[] which are less than i
        for(let i = 0; i < d; i++)
            lower[A[i] + 1] = 1;
        for(let i = 1; i <= MAX; i++)
            lower[i] = lower[i - 1] + lower[i];
   
        let flag = true;
        dp[0] = 0;
        for(let i = 1; i <= B; i++)
        {
            d2 = lower[digit[i - 1]];
            dp[i] = dp[i - 1] * d;
   
            // For first index we can't use 0
            if (i == 1 && A[0] == 0 && B != 1)
                d2 = d2 - 1;
   
            // Whether (i-1) digit of generated number
            // can be equal to (i - 1) digit of C
            if (flag)
                dp[i] += d2;
   
            // Is digit[i - 1] present in A ?
            flag = (flag & (lower[digit[i - 1] + 1] ==
                            lower[digit[i - 1]] + 1));
        }
        return dp[B];
    }
}
 
// Driver code
let arr = [ 0, 1, 2, 5 ];
let N = 2;
let k = 21;
 
document.write(solve(arr, N, k));
     
// This code is contributed by patel2127
 
</script>


Output: 

5

 

Time complexity: O(N)
Auxiliary Space: O(N), since N extra space has been taken.



Last Updated : 31 May, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads