Open In App

Count of numbers from range [L, R] whose sum of digits is Y | Set 2

Improve
Improve
Like Article
Like
Save
Share
Report

Given three positive integers L, R and Y, the task is to count the numbers in the range [L, R] whose sum of digits is equal to Y

Examples:

Input: L = 500, R = 1000, Y = 6
Output: 3
Explanation: 
Numbers in the range [500, 600] whose sum of digits is Y(= 6) are: 
501 = 5 + 0 + 1 = 6 
510 = 5 + 1 + 0 = 6 
600 = 6 + 0 + 0 = 6 
Therefore, the required output is 3.

Input: L = 20, R = 10000, Y = 14
Output: 540

Naive Approach: Refer to previous post to solve this problem by iterating over all the numbers in the range [L, R], and for every number, check if its sum of digits is equal to Y or not. If found to be true, then increment the count. Finally, print the count obtained. 

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

Efficient approach: To optimize the above approach, the idea is to use Digit DP using the following recurrence relation:

cntNum(i, sum, tight) = \sum^{9}_{i=0} cntNum(i + 1, (sum - i), tight & (i == end)


where, sum: Represents sum of digits. 
tight: Check if sum of digits exceed Y or not. 
end: Stores the maximum possible value of ith digit of a number. 
cntNum(N, Y, tight): Returns the count of numbers in the range [0, X] whose sum of digits is Y.

Before moving into the DP solution, it is good practice to write down the recursive code.

Here is the recursive code – 

C++

// C++ Program for the same approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the sum of digits
// of numbers in the range [0, X]
int cntNum(string X, int i, int sum, int tight)
{
   
    // Check if count of digits in a number
    // greater than count of digits in X
    if (i >= X.length() || sum < 0) {
 
        // Check if sum of digits of a
        // number is equal to Y
        if (sum == 0) {
            return 1;
        }
 
        return 0;
    }
 
    // Stores count of numbers whose
    // sum of digits is Y
    int res = 0;
 
    // Check if the number
    // exceeds Y or not
    int end = tight != 0 ? X[i] - '0' : 9;
 
    // Iterate over all possible
    // values of i-th digits
    for (int j = 0; j <= end; j++) {
 
        // Update res
        res += cntNum(X, i + 1, sum - j,
                    (tight > 0 & (j == end)) ==
                            true ? 1 : 0);
    }
 
    // Return res
    return res;
}
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
static int UtilCntNumRange(int L,int R,int Y)
{
 
    // Base Case
    if (R == 0 && Y == 0) {
 
        return 1;
    }
// Stores numbers in the form
    // of its equivalent String
    string str = to_string(R);
     
    // Stores count of numbers
    // in the range [0, R]
    int cntR = cntNum(str, 0, Y,
                    1);
 
    // Update str
    str = to_string(L - 1);
    // Stores count of numbers in
    // the range [0, L - 1]
    int cntL = cntNum(str, 0, Y,
                    1);
 
    return (cntR - cntL);
}
 
// Driver code
int main()
{
    int L = 20, R = 10000, Y = 14;
    cout<<(UtilCntNumRange(L, R, Y));
}
 
// This code is contributed by shinjanpatra

                    

Java

// Java program for the above approach
import java.util.*;
class GFG
{
// Function to find the sum of digits
// of numbers in the range [0, X]
static int cntNum(String X, int i, int sum,
           int tight)
 {
    // Check if count of digits in a number
    // greater than count of digits in X
    if (i >= X.length() || sum < 0) {
  
        // Check if sum of digits of a
        // number is equal to Y
        if (sum == 0) {
            return 1;
        }
  
        return 0;
    }
  
    // Stores count of numbers whose
    // sum of digits is Y
    int res = 0;
  
    // Check if the number
    // exceeds Y or not
    int end = tight != 0 ? X.charAt(i) - '0' : 9;
  
    // Iterate over all possible
    // values of i-th digits
    for (int j = 0; j <= end; j++) {
  
        // Update res
        res += cntNum(X, i + 1, sum - j,
                      (tight > 0 & (j == end)) ==
                               true ? 1 : 0);
    }
  
    // Return res
    return res;
 }
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
static int UtilCntNumRange(int L,int R,int Y)
 {
  
     // Base Case
    if (R == 0 && Y == 0) {
  
        return 1;
    }
   // Stores numbers in the form
    // of its equivalent String
    String str = String.valueOf(R);
     
     // Stores count of numbers
    // in the range [0, R]
    int cntR = cntNum(str, 0, Y,
                      1);
  
    // Update str
    str = String.valueOf(L - 1);
    // Stores count of numbers in
    // the range [0, L - 1]
    int cntL = cntNum(str, 0, Y,
                      1);
  
    return (cntR - cntL);
 }
// Driver Code
 public static void main (String[] args)
    {
      int L = 20, R = 10000, Y = 14;
      System.out.print(UtilCntNumRange(L, R, Y));
    }
}
// This code is contributed by Debojyoti Mandal

                    

Python3

# Python program for the above approach
# Function to find the sum of digits
# of numbers in the range [0, X]
def cntNum(X, i, sum, tight):
 
    # Check if count of digits in a number
    # greater than count of digits in X
    if (i >= len(X) or sum < 0):
  
        # Check if sum of digits of a
        # number is equal to Y
        if (sum == 0):
            return 1
     
        return 0
  
    # Stores count of numbers whose
    # sum of digits is Y
    res = 0
  
    # Check if the number
    # exceeds Y or not
    end = ord(X[i]) - ord('0') if tight else 9
  
    # Iterate over all possible
    # values of i-th digits
    for j in range(end+1):
  
        # Update res
        res += cntNum(X, i + 1, sum - j,1 if((tight > 0 and (j == end)) == True) else 0)
  
    # Return res
    return res
 
# Utility function to count the numbers in
# the range [L, R] whose sum of digits is Y
def UtilCntNumRange(L, R, Y):
 
     # Base Case
    if (R == 0 and Y == 0):
  
        return 1
 
    # Stores numbers in the form
    # of its equivalent String
    Str = str(R)
 
     # Stores count of numbers
    # in the range [0, R]
    cntR = cntNum(Str, 0, Y,1)
  
    # Update str
    Str = str(L - 1)
     
    # Stores count of numbers in
    # the range [0, L - 1]
    cntL = cntNum(Str, 0, Y, 1)
  
    return (cntR - cntL)
 
# Driver Code
 
L, R, Y = 20, 10000, 14
print(UtilCntNumRange(L, R, Y))
 
# This code is contributed by shinjanpatra

                    

C#

// C# program for the above approach
using System;
class GFG
{
   
    // Function to find the sum of digits
    // of numbers in the range [0, X]
    static int cntNum(string X, int i, int sum, int tight)
    {
       
        // Check if count of digits in a number
        // greater than count of digits in X
        if (i >= X.Length || sum < 0) {
 
            // Check if sum of digits of a
            // number is equal to Y
            if (sum == 0) {
                return 1;
            }
 
            return 0;
        }
 
        // Stores count of numbers whose
        // sum of digits is Y
        int res = 0;
 
        // Check if the number
        // exceeds Y or not
        int end = tight != 0 ? X[i] - '0' : 9;
 
        // Iterate over all possible
        // values of i-th digits
        for (int j = 0; j <= end; j++) {
 
            // Update res
            res += cntNum(
                X, i + 1, sum - j,
                (tight > 0 & (j == end)) == true ? 1 : 0);
        }
 
        // Return res
        return res;
    }
    // Utility function to count the numbers in
    // the range [L, R] whose sum of digits is Y
    static int UtilCntNumRange(int L, int R, int Y)
    {
        // Base Case
        if (R == 0 && Y == 0) {
 
            return 1;
        }
        // Stores numbers in the form
        // of its equivalent String
        string str = R.ToString();
 
        // Stores count of numbers
        // in the range [0, R]
        int cntR = cntNum(str, 0, Y, 1);
 
        // Update str
        str = (L - 1).ToString();
        // Stores count of numbers in
        // the range [0, L - 1]
        int cntL = cntNum(str, 0, Y, 1);
 
        return (cntR - cntL);
    }
   
    // Driver Code
    public static void Main(string[] args)
    {
        int L = 20, R = 10000, Y = 14;
        Console.WriteLine(UtilCntNumRange(L, R, Y));
    }
}
 
// This code is contributed by ukasp.

                    

Javascript

// JavaScript program for the above approach
// Function to find the sum of digits
// of numbers in the range [0, X]
function cntNum( X, i, sum, tight)
 {
    // Check if count of digits in a number
    // greater than count of digits in X
    if (i >= X.length || sum < 0) {
  
        // Check if sum of digits of a
        // number is equal to Y
        if (sum == 0) {
            return 1;
        }
  
        return 0;
    }
  
    // Stores count of numbers whose
    // sum of digits is Y
    var res = 0;
  
    // Check if the number
    // exceeds Y or not
    var end = tight != 0 ? X[i].charCodeAt(0) - '0'.charCodeAt(0) : 9;
  
    // Iterate over all possible
    // values of i-th digits
    for (var j = 0; j <= end; j++) {
  
        // Update res
        res += cntNum(X, i + 1, sum - j,
                      (tight > 0 & (j == end)) ==
                               true ? 1 : 0);
    }
  
    // Return res
    return res;
 }
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
function UtilCntNumRange(L, R, Y)
 {
     // Base Case
    if (R == 0 && Y == 0) {
  
        return 1;
    }
   // Stores numbers in the form
    // of its equivalent String
    var str = (R).toString();
     
     // Stores count of numbers
    // in the range [0, R]
    var cntR = cntNum(str, 0, Y,
                      1);
  
    // Update str
     str = (L - 1).toString();
    // Stores count of numbers in
    // the range [0, L - 1]
    var cntL = cntNum(str, 0, Y,
                      1);
  
    return (cntR - cntL);
 }
// Driver Code
 
      var L = 20, R = 10000, Y = 14;
      document.write(UtilCntNumRange(L, R, Y));
     
 
// This code is contributed by shivanisinghss2110

                    

Output
540

Follow the steps below to solve the problem using DP.

  1. Initialize a 3D array dp[N][Y][tight] to compute and store the values of all subproblems of the above recurrence relation.
  2. Finally, return the value of dp[N][sum][tight].

Below is the implementation of the above approach:

C++

// CPP program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
#define M 1000
 
// Function to find the sum of digits
// of numbers in the range [0, X]
int cntNum(string X, int i, int sum,
           int tight, int dp[M][M][2])
{
    // Check if count of digits in a number
    // greater than count of digits in X
    if (i >= X.length() || sum < 0) {
 
        // If sum of digits of a
        // number is equal to Y
        if (sum == 0) {
            return 1;
        }
 
        return 0;
    }
 
    // Check if current subproblem has
    // already been computed
    if (dp[sum][i][tight] != -1) {
        return dp[sum][i][tight];
    }
 
    // Stores count of numbers whose
    // sum of digits is Y
    int res = 0;
 
    // Check if the number
    // exceeds Y or not
    int end = tight ? X[i] - '0' : 9;
 
    // Iterate over all possible
    // values of i-th digits
    for (int j = 0; j <= end; j++) {
 
        // Update res
        res += cntNum(X, i + 1, sum - j,
                      (tight & (j == end)), dp);
    }
 
    // Return res
    return dp[sum][i][tight]=res;
}
 
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
int UtilCntNumRange(int L, int R, int Y)
{
    // Base Case
    if (R == 0 && Y == 0) {
 
        return 1;
    }
 
    // Stores numbers in the form
    // of its equivalent string
    string str = to_string(R);
 
    // Stores overlapping subproblems
    int dp[M][M][2];
 
    // Initialize dp[][][]
    memset(dp, -1, sizeof(dp));
 
    // Stores count of numbers
    // in the range [0, R]
    int cntR = cntNum(str, 0, Y,
                      true, dp);
 
    // Update str
    str = to_string(L - 1);
 
    // Initialize dp[][][]
    memset(dp, -1, sizeof(dp));
 
    // Stores count of numbers in
    // the range [0, L - 1]
    int cntL = cntNum(str, 0, Y,
                      true, dp);
 
    return (cntR - cntL);
}
 
// Driver Code
int main()
{
    int L = 20, R = 10000, Y = 14;
    cout << UtilCntNumRange(L, R, Y);
}

                    

Java

// Java program for the above approach
import java.util.*;
 
class GFG{
 
static final int M = 1000;
 
// Function to find the sum of digits
// of numbers in the range [0, X]
static int cntNum(String X, int i, int sum,
           int tight, int dp[][][])
{
    // Check if count of digits in a number
    // greater than count of digits in X
    if (i >= X.length() || sum < 0) {
 
        // Check if sum of digits of a
        // number is equal to Y
        if (sum == 0) {
            return 1;
        }
 
        return 0;
    }
 
    // Check if current subproblem has
    // already been computed
    if (dp[sum][i][tight] != -1) {
        return dp[sum][i][tight];
    }
 
    // Stores count of numbers whose
    // sum of digits is Y
    int res = 0;
 
    // Check if the number
    // exceeds Y or not
    int end = tight != 0 ? X.charAt(i) - '0' : 9;
 
    // Iterate over all possible
    // values of i-th digits
    for (int j = 0; j <= end; j++) {
 
        // Update res
        res += cntNum(X, i + 1, sum - j,
                      (tight > 0 & (j == end)) ==
                               true ? 1 : 0, dp);
    }
 
    // Return res
    return dp[sum][i][tight]=res;
}
 
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
static int UtilCntNumRange(int L, int R, int Y)
{
    // Base Case
    if (R == 0 && Y == 0) {
 
        return 1;
    }
 
    // Stores numbers in the form
    // of its equivalent String
    String str = String.valueOf(R);
 
    // Stores overlapping subproblems
    int [][][]dp = new int[M][M][2];
 
    // Initialize dp[][][]
    for(int i = 0; i < M; i++)
    {
        for (int j = 0; j < M; j++) {
            for (int k = 0; k < 2; k++)
                dp[i][j][k] = -1;
        }
    }
 
    // Stores count of numbers
    // in the range [0, R]
    int cntR = cntNum(str, 0, Y,
                      1, dp);
 
    // Update str
    str = String.valueOf(L - 1);
 
    // Initialize dp[][][]
    for(int i = 0; i < M; i++)
    {
        for (int j = 0; j < M; j++) {
            for (int k = 0; k < 2; k++)
                dp[i][j][k] = -1;
        }
    }
 
    // Stores count of numbers in
    // the range [0, L - 1]
    int cntL = cntNum(str, 0, Y,
                      1, dp);
 
    return (cntR - cntL);
}
 
// Driver Code
public static void main(String[] args)
{
    int L = 20, R = 10000, Y = 14;
    System.out.print(UtilCntNumRange(L, R, Y));
}
}
 
// This code is contributed by shikhasingrajput

                    

Python3

# Python program for the above approach
M = 1000
 
# Function to find the sum of digits
# of numbers in the range [0, X]
def cntNum(X, i, sum, tight, dp):
   
    # Check if count of digits in a number
    # greater than count of digits in X
    if (i >= len(X) or sum < 0):
 
        # Check if sum of digits of a
        # number is equal to Y
        if (sum == 0):
            return 1
 
        return 0
 
    # Check if current subproblem has
    # already been computed
    if (dp[sum][i][tight] != -1):
        return dp[sum][i][tight]
 
    # Stores count of numbers whose
    # sum of digits is Y
    res, end = 0, 9
 
    # Check if the number
    # exceeds Y or not
    if tight:
        end = ord(X[i]) - ord('0')
    # end = tight ? X[i] - '0' : 9;
 
    # Iterate over all possible
    # values of i-th digits
    for j in range(end + 1):
 
        # Update res
        res += cntNum(X, i + 1, sum - j,
                      (tight & (j == end)), dp)
 
    # Return res
    dp[sum][i][tight] = res
    return res
 
# Utility function to count the numbers in
# the range [L, R] whose sum of digits is Y
def UtilCntNumRange(L, R, Y):
   
    # Base Case
    if (R == 0 and Y == 0):
 
        return 1
 
    # Stores numbers in the form
    # of its equivalent
    strr = str(R)
 
    # Stores overlapping subproblems
    dp = [[[-1 for i in range(2)] for i in range(M)]
                                  for i in range(M)]
 
    # Initialize dp[][][]
    # memset(dp, -1, sizeof(dp))
 
    # Stores count of numbers
    # in the range [0, R]
    cntR = cntNum(strr, 0, Y, True, dp)
 
    # Update str
    strr = str(L - 1)
 
    # Initialize dp[][][]
    # memset(dp, -1, sizeof(dp))
 
    # Stores count of numbers in
    # the range [0, L - 1]
    cntL = cntNum(strr, 0, Y, True, dp)
 
    return (cntR - cntL)
 
# Driver Code
if __name__ == '__main__':
    L, R, Y = 20, 10000, 14
    print(UtilCntNumRange(L, R, Y))
 
# This code is contributed by mohit kumar 29

                    

C#

// C# program for the above approach
using System;
 
class GFG{
 
static readonly int M = 1000;
 
// Function to find the sum of digits
// of numbers in the range [0, X]
static int cntNum(String X, int i, int sum,
                 int tight, int [,,]dp)
{
     
    // Check if count of digits in a number
    // greater than count of digits in X
    if (i >= X.Length || sum < 0)
    {
         
        // Check if sum of digits of a
        // number is equal to Y
        if (sum == 0)
        {
            return 1;
        }
        return 0;
    }
 
    // Check if current subproblem has
    // already been computed
    if (dp[sum, i, tight] != -1)
    {
        return dp[sum, i, tight];
    }
 
    // Stores count of numbers whose
    // sum of digits is Y
    int res = 0;
 
    // Check if the number
    // exceeds Y or not
    int end = tight != 0 ? X[i] - '0' : 9;
 
    // Iterate over all possible
    // values of i-th digits
    for(int j = 0; j <= end; j++)
    {
         
        // Update res
        res += cntNum(X, i + 1, sum - j,
                    (tight > 0 & (j == end)) ==
                      true ? 1 : 0, dp);
    }
 
    // Return res
    return dp[sum][i][tight] = res;
}
 
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
static int UtilCntNumRange(int L, int R, int Y)
{
     
    // Base Case
    if (R == 0 && Y == 0)
    {
        return 1;
    }
 
    // Stores numbers in the form
    // of its equivalent String
    String str = String.Join("", R);
     
    // Stores overlapping subproblems
    int [,,]dp = new int[M, M, 2];
 
    // Initialize [,]dp[]
    for(int i = 0; i < M; i++)
    {
        for(int j = 0; j < M; j++)
        {
            for(int k = 0; k < 2; k++)
                dp[i, j, k] = -1;
        }
    }
 
    // Stores count of numbers
    // in the range [0, R]
    int cntR = cntNum(str, 0, Y,
                      1, dp);
 
    // Update str
    str = String.Join("",L - 1);
 
    // Initialize [,]dp[]
    for(int i = 0; i < M; i++)
    {
        for(int j = 0; j < M; j++)
        {
            for(int k = 0; k < 2; k++)
                dp[i, j, k] = -1;
        }
    }
 
    // Stores count of numbers in
    // the range [0, L - 1]
    int cntL = cntNum(str, 0, Y,
                      1, dp);
 
    return (cntR - cntL);
}
 
// Driver Code
public static void Main(String[] args)
{
    int L = 20, R = 10000, Y = 14;
     
    Console.Write(UtilCntNumRange(L, R, Y));
}
}
 
// This code is contributed by 29AjayKumar

                    

Javascript

<script>
// Javascript program for the above approach
let M = 1000;
 
// Function to find the sum of digits
// of numbers in the range [0, X]
function cntNum(X, i, sum, tight, dp)
{
 
    // Check if count of digits in a number
    // greater than count of digits in X
    if (i >= X.length || sum < 0) {
  
        // Check if sum of digits of a
        // number is equal to Y
        if (sum == 0) {
            return 1;
        }
  
        return 0;
    }
  
    // Check if current subproblem has
    // already been computed
    if (dp[sum][i][tight] != -1) {
        return dp[sum][i][tight];
    }
  
    // Stores count of numbers whose
    // sum of digits is Y
    let res = 0;
  
    // Check if the number
    // exceeds Y or not
    let end = tight != 0 ? X[i].charCodeAt(0) - '0'.charCodeAt(0) : 9;
  
    // Iterate over all possible
    // values of i-th digits
    for (let j = 0; j <= end; j++) {
  
        // Update res
        res += cntNum(X, i + 1, sum - j,
                      (tight > 0 & (j == end)) ==
                               true ? 1 : 0, dp);
    }
  
    // Return res
    return dp[sum][i][tight]=res;
}
 
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
function UtilCntNumRange(L,R,Y)
{
    // Base Case
    if (R == 0 && Y == 0) {
  
        return 1;
    }
  
    // Stores numbers in the form
    // of its equivalent String
    let str = (R).toString();
  
    // Stores overlapping subproblems
    let dp = new Array(M);
  
    // Initialize dp[][][]
    for(let i = 0; i < M; i++)
    {
        dp[i]=new Array(M);
        for (let j = 0; j < M; j++) {
            dp[i][j]=new Array(2);
            for (let k = 0; k < 2; k++)
                dp[i][j][k] = -1;
        }
    }
  
    // Stores count of numbers
    // in the range [0, R]
    let cntR = cntNum(str, 0, Y,
                      1, dp);
  
    // Update str
    str = (L - 1).toString();
  
    // Initialize dp[][][]
    for(let i = 0; i < M; i++)
    {
        for (let j = 0; j < M; j++) {
            for (let k = 0; k < 2; k++)
                dp[i][j][k] = -1;
        }
    }
  
    // Stores count of numbers in
    // the range [0, L - 1]
    let cntL = cntNum(str, 0, Y,
                      1, dp);
  
    return (cntR - cntL);
}
 
// Driver Code
let L = 20, R = 10000, Y = 14;
document.write(UtilCntNumRange(L, R, Y));
 
// This code is contributed by patel2127
</script>

                    

Output
540

Time Complexity: O(Y * log10(R) * 10)
Auxiliary Space: O(Y * log10(R)



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