Count numbers that does not contain digit N in given range

Given integers, N, L, and R, the task is to find the number of integers in the range L to R that does not contain the digit N. print the answer modulo 109 + 7. ( L ? R ? 101000000)
Examples:
Input: N = 5, L = 1, R = 10
Output: 9
Explanation: excluding all 5 others from 1 to 10 will be included in the answer.Input: N = 5, L = 1, R = 100
Output: 81
Explanation: Excluding 5, 15, 25, 35, 45, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 65, 75, 85, and 95 all numbers from 1 to 100 will be included in the answer
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(18N), Where N is the number of digits to be filled.
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] represents numbers in the range with i digits and j represents tight condition.
- 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 store the value of a state and whenever the function is called, return the stored value without computing again.
- First answer will be calculated for 0 to A – 1 and then calculated for 0 to B then latter one is subtracted with prior one to get answer for range [L, R]
Follow the steps below to solve the problem:
- Create a recursive function that takes two parameters i representing the position to be filled and j representing the tight condition.
- Call the recursive function for choosing all digits from 0 to 9 apart from N.
- Base case if size digit formed return 1;
- Create a 2d array dp[N][2] initially filled with -1.
- If the answer for a particular state is computed then save it in dp[i][j].
- If the answer for a particular state is already computed then just return dp[i][j].
Below is the implementation of the above approach:
C++
// C++ code to implement the approach#include <bits/stdc++.h>using namespace std;Â
const int MOD = 1e9 + 7;Â
// dp table initialized with -1int dp[100001][2];Â
// Recursive Function to find numbers// in the range L to R such that they// do not contain digit Nint recur(int i, int j, int N, string& a){    // Base case    if (i == a.size()) {        return 1;    }Â
    // If answer for current state is already    // calculated then just return dp[i][j]    if (dp[i][j] != -1)        return dp[i][j];Â
    // Answer initialized with zero    int ans = 0;Â
    // Tight condition true    if (j == 1) {Â
        // Iterating from 0 to max value        // of tight condition          cout<<((int)a[i] - 48)<<endl;        for (int k = 0; k <= ((int)a[i] - 48); k++) {Â
            // N is not allowed to use            if (k == N)                continue;Â
            // When k is at max tight condition            // remains even in next state            if (k == ((int)a[i] - 48))Â
                // Calling recursive function                // for tight digit                ans += recur(i + 1, 1, N, a);Â
            // Tight condition drops            else                // Calling recursive function                // for digits less than tight                // condition digit                ans += recur(i + 1, 0, N, a);        }    }Â
    // Tight condition false    else {Â
        // Iterating for all digits        for (int k = 0; k <= 9; k++) {Â
            // Digit N is not possible            if (k == N)                continue;Â
            // Calling recursive function for            // all digits from 0 to 9            ans += recur(i + 1, 0, N, a);        }    }Â
    // Save and return dp value    return dp[i][j] = ans;}Â
// Function to find numbers// in the range L to R such that they// do not contain digit Nint countInRange(int N, 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 sum of digits T from    // 1 to L - 1    int ans1 = recur(0, 1, N, L);Â
    // Initializing dp array with - 1    memset(dp, -1, sizeof(dp));Â
    // Numbers with sum of digits T in the    // range 1 to R    int ans2 = recur(0, 1, N, R);Â
    // Difference of ans2 and ans1    // will generate answer for required    // range    return ans2 - ans1;}Â
// Driver Codeint main(){Â Â Â Â // Input 1Â Â Â Â int N = 5, L = 1, R = 10;Â
    // Function Call    cout << countInRange(N, L, R) << endl;Â
    // Input 2    //int N1 = 5, L1 = 1, R1 = 100;Â
    // Function Call    //cout << countInRange(N1, L1, R1) << endl;    return 0;} |
Java
// Java code to implement the approachÂ
import java.io.*;import java.util.*;Â
class GFG {Â
    static final int MOD = 1_000_000_007;Â
    // dp table initialized with -1    static int[][] dp = new int[100001][2];Â
    // Recursive Function to find numbers    // in the range L to R such that they    // do not contain digit N    static int recur(int i, int j, int N, String a)    {        // Base case        if (i == a.length()) {            return 1;        }Â
        // If answer for current state is already        // calculated then just return dp[i][j]        if (dp[i][j] != -1)            return dp[i][j];Â
        // Answer initialized with zero        int ans = 0;Â
        // Tight condition true        if (j == 1) {            // Iterating from 0 to max value            // of tight condition            for (int k = 0; k <= a.charAt(i) - '0'; k++) {                // N is not allowed to use                if (k == N)                    continue;                // When k is at max tight condition                // remains even in next state                if (k == a.charAt(i) - '0')                    // Calling recursive function                    // for tight digit                    ans += recur(i + 1, 1, N, a);                // Tight condition drops                else                    ans += recur(i + 1, 0, N, a);            }        }        // Tight condition false        else {            // Iterating for all digits            for (int k = 0; k <= 9; k++) {                // Digit N is not possible                if (k == N)                    continue;                // Calling recursive function for                // all digits from 0 to 9                ans += recur(i + 1, 0, N, a);            }        }Â
        // Save and return dp value        return dp[i][j] = ans;    }Â
    // Function to find numbers    // in the range L to R such that they    // do not contain digit N    static int countInRange(int N, int A, int B)    {        // Initializing dp array with - 1        for (int[] row : dp) {            Arrays.fill(row, -1);        }Â
        A--;        String L = Integer.toString(A);        String R = Integer.toString(B);Â
        // Numbers with sum of digits T from        // 1 to L - 1        int ans1 = recur(0, 1, N, L);Â
        // Initializing dp array with - 1        for (int[] row : dp) {            Arrays.fill(row, -1);        }Â
        // Numbers with sum of digits T in the        // range 1 to R        int ans2 = recur(0, 1, N, R);Â
        // Difference of ans2 and ans1        // will generate answer for required        // range        return ans2 - ans1;    }Â
    public static void main(String[] args)    {        // Input 1        int N = 5;        int L = 1;        int R = 10;Â
        // Function Call        System.out.println(countInRange(N, L, R));Â
        // Input 2        int N1 = 5;        int L1 = 1;        int R1 = 100;Â
        // Function Call        System.out.println(countInRange(N1, L1, R1));    }}Â
// This contributed by lokeshmvs21. |
Python3
# Python code to implement the approachMOD = 1e9 + 7;Â
# dp table initialized with -1dp= [[-1]*(2) for _ in range(100001)];Â
# Recursive Function to find numbers# in the range L to R such that they# do not contain digit Ndef recur(i, j, N, a):    # Base case    if (i == len(a)) :        return 1;         # If answer for current state is already    # calculated then just return dp[i][j]    if (dp[i][j] != -1):        return dp[i][j];Â
    # Answer initialized with zero    ans = 0;Â
    # Tight condition true    if (j == 1) :Â
        # Iterating from 0 to max value        # of tight condition        for k in range(0, int(a[i])+1):Â
            # N is not allowed to use            if (k == N):                continue;Â
            # When k is at max tight condition            # remains even in next state            if (k == int(a[i])):Â
                # Calling recursive function                # for tight digit                ans += recur(i + 1, 1, N, a);Â
            # Tight condition drops            else:                # Calling recursive function                # for digits less than tight                # condition digit                ans += recur(i + 1, 0, N, a);         Â
    # Tight condition false    else :        # Iterating for all digits        for k in range(0,10):Â
            # Digit N is not possible            if (k == N):                continue;Â
            # Calling recursive function for            # all digits from 0 to 9            ans += recur(i + 1, 0, N, a);         Â
    # Save and return dp value    dp[i][j]=ans;    return dp[i][j];Â
# Function to find numbers# in the range L to R such that they# do not contain digit Ndef countInRange( N, A, B):    # Initializing dp array with - 1    for i in range(0,100001):        for j in range(0,2):            dp[i][j]=-1;         A -= 1;    L = str(A);    R = str(B);Â
    # Numbers with sum of digits T from    # 1 to L - 1    ans1 = recur(0, 1, N, L);Â
    # Initializing dp array with - 1    for i in range(0,100001):        for j in range(0,2):            dp[i][j]=-1;    # Numbers with sum of digits T in the    # range 1 to R    ans2 = recur(0, 1, N, R);Â
    # Difference of ans2 and ans1    # will generate answer for required    # range    return ans2 - ans1;Â
# Driver Code# Input 1N = 5;L = 1;R = 10;Â
# Function Callprint(countInRange(N, L, R));Â
# Input 2N1 = 5;L1 = 1;R1 = 100;Â
# Function Callprint(countInRange(N1, L1, R1));Â
# This code is contributed by agrawalpooja976. |
C#
using System;Â
namespace GFG{  static class Program  {    static readonly int MOD = 1_000_000_007;Â
    // dp table initialized with -1    static int[,] dp = new int[100001, 2];Â
    // Recursive Function to find numbers    // in the range L to R such that they    // do not contain digit N    static int Recur(int i, int j, int N, string a)    {      // Base case      if (i == a.Length)      {        return 1;      }Â
      // If answer for current state is already      // calculated then just return dp[i][j]      if (dp[i, j] != -1)        return dp[i, j];Â
      // Answer initialized with zero      int ans = 0;Â
      // Tight condition true      if (j == 1)      {        // Iterating from 0 to max value        // of tight condition        for (int k = 0; k <= a[i] - '0'; k++)        {          // N is not allowed to use          if (k == N)            continue;Â
          // When k is at max tight condition          // remains even in next state          if (k == a[i] - '0')            // Calling recursive function            // for tight digit            ans += Recur(i + 1, 1, N, a);          // Tight condition drops          else            ans += Recur(i + 1, 0, N, a);        }      }      // Tight condition false      else      {        // Iterating for all digits        for (int k = 0; k <= 9; k++)        {          // Digit N is not possible          if (k == N)            continue;          // Calling recursive function for          // all digits from 0 to 9          ans += Recur(i + 1, 0, N, a);        }      }Â
      // Save and return dp value      return dp[i, j] = ans;    }Â
    // Function to find numbers    // in the range L to R such that they    // do not contain digit N    static int CountInRange(int N, 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++)        {          dp[i, j] = -1;        }      }Â
      A--;      string L = A.ToString();      string R = B.ToString();Â
      // Numbers with sum of digits T from      // 1 to L - 1      int ans1 = Recur(0, 1, N, L);Â
      // Initializing dp array with - 1      for (int i = 0; i < dp.GetLength(0); i++)      {        for (int j = 0; j < dp.GetLength(1); j++)        {          dp[i, j] = -1;        }      }Â
      // Numbers with sum of digits T in the      // range 1 to R      int ans2 = Recur(0, 1, N, R);Â
      // Difference of ans2 and ans1      // will generate answer for required      // range      return ans2 - ans1;    }Â
    // Main Method    static void Main(string[] args)    {      // Input 1      int N = 5;      int L = 1;      int R = 10;Â
      // Function Call      Console.WriteLine(CountInRange(N, L, R));Â
      // Input 2      int N1 = 5;      int L1 = 1;      int R1 = 100;Â
      // Function Call      Console.WriteLine(CountInRange(N1, L1, R1));    }  }}Â
// This code is contributed by surajrasr7277 |
Javascript
// Javascript code to implement the approachÂ
let MOD = 1e9 + 7;Â
// dp table initialized with -1let dp = new Array(100001);for(let i=0; i<100001; i++)Â Â Â Â dp[i]= new Array(2);Â
Â
// Recursive Function to find numbers// in the range L to R such that they// do not contain digit Nfunction recur(i, j, N, a){    // Base case    if (i == a.length) {        return 1;    }Â
    // If answer for current state is already    // calculated then just return dp[i][j]    if (dp[i][j] != -1)        return dp[i][j];Â
    // Answer initialized with zero    let ans = 0;Â
    // Tight condition true    if (j == 1) {Â
        // Iterating from 0 to max value        // of tight condition        for (let k = 0; k <= (parseInt(a[i])); k++) {Â
            // N is not allowed to use            if (k == N)                continue;Â
            // When k is at max tight condition            // remains even in next state            if (k == (parseInt(a[i])))Â
                // Calling recursive function                // for tight digit                ans = ans + recur(i + 1, 1, N, a);                             // Tight condition drops            else                // Calling recursive function                // for digits less than tight                // condition digit                 ans = ans + recur(i + 1, 0, N, a);        }    }Â
    // Tight condition false    else {Â
        // Iterating for all digits        for (let k = 0; k <= 9; k++) {Â
            // Digit N is not possible            if (k == N)                continue;Â
            // Calling recursive function for            // all digits from 0 to 9            ans += recur(i + 1, 0, N, a);        }    }Â
    // Save and return dp value    return dp[i][j] = ans;}Â
// Function to find numbers// in the range L to R such that they// do not contain digit Nfunction countInRange(N, A, B){Â
    // Initializing dp array with - 1    for(let i=0; i<100001; i++)        for(let j=0; j<2; j++)            dp[i][j]=-1;    A--;    let L = A.toString(), R = B.toString();Â
    // Numbers with sum of digits T from    // 1 to L - 1    let ans1 = recur(0, 1, N, L);Â
    // Initializing dp array with - 1    for(let i=0; i<100001; i++)        for(let j=0; j<2; j++)            dp[i][j]=-1;    // Numbers with sum of digits T in the    // range 1 to R    let ans2 = recur(0, 1, N, R);Â
    // Difference of ans2 and ans1    // will generate answer for required    // range    return ans2 - ans1;}Â
// Driver Code    // Input 1    let N = 5, L = 1, R = 10;Â
    // Function Call    document.write(countInRange(N, L, R));         document.write("<br>");Â
    // Input 2    let N1 = 5, L1 = 1, R1 = 100;Â
    // Function Call    document.write(countInRange(N1, L1, R1)); |
9 81
Time Complexity: O(N), Where N is the number of digits to be filled
Auxiliary Space: O(N)
Related Articles:
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



