Open In App

Count number of integers in given range with adjacent digits different and sum of digits equal to M

Last Updated : 23 Feb, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

Given integers T, A, and B, the task for this problem is to find numbers in the range [A, B] such that the adjacent digits of the number are different and the sum of digits is equal to T. ( A ? B ? 1018)

Examples:

Input: T = 5, A = 1, B = 100
Output: 6
Explanation: 5, 14, 23, 32,  41, and 50 are valid integers that are in between the range 1 to 100 and have the sum of digits 5 along with adjacent digits different.

Input: T = 5, A = 1, B = 100000000
Output: 74

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 from 0 to 9.
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][sum] represents numbers with i digits, j is the tight condition pointer, k is the last digit taken and the sum is digit sum till i.
  • 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.

Follow the steps below to solve the problem:

  • Create a recursive function that takes four parameters i represents a position to be filled, j represents the tight condition pointer, k represents the last digit taken and sum represents the total sum of digits.
  • Call the recursive function for choosing all digits from 0 to 9.
  • Base case if N size digit formed and the sum of digits equal to T return 1 else return 0.
  • Create a 4d array  dp[21][21][10][190] initially filled with -1.
  • If the answer for a particular state is computed then save it in dp[i][j][k][sum].
  • If the answer for a particular state is already computed then just return dp[i][j][k][sum].

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 -1
int dp[21][21][10][190];

// Recursive Function to find numbers
// in the range A to B such that adjacent
// digits are different and their sum is
// equal to T
int recur(int i, int j, int k, int sum, int T, string& a)
{
    // Base case
    if (i == a.size()) {

        // If current sum is equal to T
        if (sum == T)
            return 1;

        // If not equal to T
        else
            return 0;
    }

    // If answer for current state is already
    // calculated then just
    // return dp[i][j][k][sum]
    if (dp[i][j][k][sum] != -1)
        return dp[i][j][k][sum];

    // Answer initialized with zero
    int ans = 0;

    // Choosing first value
    if (i == 0) {

        // Iterating from 0 to maxvalue
        // of digit current position
        // can have
        for (int l = 0; l <= (int)(a[j] - 48); l++) {

            // l is maximum value of digit
            if (l == (int)(a[j] - 48)) {

                // Calling recursive function
                // for selecting last max digit
                // for current position
                ans += recur(i + 1, j + 1, l, sum + l, T,
                             a);
            }

            else

                // Calling recursive function
                // for selecting l as current
                // digit and its not max digit
                ans += recur(i + 1, j, l, sum + l, T, a);
        }
    }

    else {

        // Digits taken till now were
        // all zero
        if (sum == 0) {

            // All digits can be possible
            // from 0 to 9
            for (int l = 0; l <= 9; l++) {

                // Calling recursive function
                // for all digits from 0 to 9
                ans += recur(i + 1, j, l, sum + l, T, a);
            }
        }

        // Already non zero digits are taken
        else {

            // Iterating from 0 to 9
            for (int l = 0; l <= 9; l++) {

                // If max digit was taken
                // last time
                if (j == i) {

                    // If current digit
                    // is different
                    if (l <= (int)(a[j] - 48) and l != k) {

                        // max digit taken calling
                        // recursive function
                        if (l == (int)(a[j] - 48))
                            ans += recur(i + 1, j + 1, l,
                                         sum + l, T, a);

                        // Calling recursive
                        // function for non
                        // max digit
                        else
                            ans += recur(i + 1, j, l,
                                         sum + l, T, a);
                    }
                }

                // If max digit was not taken
                else if (l != k)
                    ans += recur(i + 1, j, l, sum + l, T,
                                 a);
            }
        }
    }

    // Save and return dp value
    return dp[i][j][k][sum] = ans;
}

// Function to find numbers
// in the range A to B such that adjacent
// digits are different and their sum is
// equal to T
int countInRange(int T, 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, 0, 0, 0, T, 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, 0, 0, 0, T, R);

    // Difference of ans2 and ans1
    // will generate answer for
    // required range
    return ans2 - ans1;
}

// Driver Code
int main()
{

    // Input 1
    int T = 5, A = 1, B = 100;

    // Function Call
    cout << countInRange(T, A, B) << endl;

    // Input 2
    int T1 = 5, A1 = 1, B1 = 100000000;

    // Function Call
    cout << countInRange(T1, A1, B1) << endl;
    return 0;
}
Java
// Java code to implement the approach
import java.io.*;
import java.util.*;

class GFG {

  static final int MOD = (int)1e9 + 7;
  static int dp[][][][];

  // Dp table initialized with -1
  static void memset(int[][][][] dp)
  {
    for (int i = 0; i < 21; i++) {
      dp[i] = new int[21][10][190];
      for (int j = 0; j < 21; j++) {
        for (int k = 0; k < 10; k++) {
          Arrays.fill(dp[i][j][k], -1);
        }
      }
    }
  }

  // Recursive Function to find numbers in the range A to
  // B such that adjacent digits are different and their
  // sum is equal to T
  static int recur(int i, int j, int k, int sum, int T,
                   char a[])
  {
    // Base case
    if (i == a.length) {

      // If current sum is equal to T
      if (sum == T) {
        return 1;
      }

      // If not equal to T
      else {
        return 0;
      }
    }

    // If answer for current state is already calculated
    // then just return dp[i][j][k][sum]
    if (dp[i][j][k][sum] != -1) {
      return dp[i][j][k][sum];
    }

    // Answer initialized with zero
    int ans = 0;

    // Choosing first value
    if (i == 0) {

      // Iterating from 0 to maxvalue
      // of digit current position
      // can have
      for (int l = 0; l <= (a[j] - '0'); l++) {

        // l is maximum value of digit
        if (l == (a[j] - '0')) {

          // Calling recursive function
          // for selecting last max digit
          // for current position
          ans += recur(i + 1, j + 1, l, sum + l,
                       T, a);
        }
        else {

          // Calling recursive function
          // for selecting l as current
          // digit and its not max digit
          ans += recur(i + 1, j, l, sum + l, T,
                       a);
        }
      }
    }
    else {

      // Digits taken till now were
      // all zero
      if (sum == 0) {

        // All digits can be possible
        // from 0 to 9
        for (int l = 0; l <= 9; l++) {

          // Calling recursive function
          // for all digits from 0 to 9
          ans += recur(i + 1, j, l, sum + l, T,
                       a);
        }
      }

      // Already non zero digits are taken
      else {

        // Iterating from 0 to 9
        for (int l = 0; l <= 9; l++) {

          // If max digit was taken
          // last time
          if (j == i) {

            // If current digit
            // is different
            if (l <= (a[j] - '0') && l != k) {

              // max digit taken calling
              // recursive function
              if (l == (a[j] - '0')) {
                ans += recur(i + 1, j + 1,
                             l, sum + l, T,
                             a);
              }

              // Calling recursive
              // function for non
              // max digit
              else {
                ans += recur(i + 1, j, l,
                             sum + l, T, a);
              }
            }
          }

          // If max digit was not taken
          else if (l != k) {
            ans += recur(i + 1, j, l, sum + l,
                         T, a);
          }
        }
      }
    }

    // Save and return dp value
    return dp[i][j][k][sum] = ans;
  }

  // Function to find numbers
  // in the range A to B such that adjacent
  // digits are different and their sum is
  // equal to T
  static int countInRange(int T, int A, int B)
  {
    dp = new int[21][21][10][190];

    // Initializing dp array with - 1
    memset(dp);
    String L = Integer.toString(A - 1);
    String R = Integer.toString(B);

    // Numbers with sum of digits T from
    // 1 to L - 1
    int ans1 = recur(0, 0, 0, 0, T, L.toCharArray());

    // Initializing dp array with - 1
    memset(dp);

    // Numbers with sum of digits T in
    // the range 1 to R
    int ans2 = recur(0, 0, 0, 0, T, R.toCharArray());

    // Difference of ans2 and ans1
    // will generate answer for
    // required range
    return ans2 - ans1;
  }

  public static void main(String[] args)
  {
    // Input 1
    int T = 5, A = 1, B = 100;

    // Function Call
    System.out.println(countInRange(T, A, B));

    // Input 2
    int T1 = 5, A1 = 1, B1 = 100000000;

    // Function Call
    System.out.println(countInRange(T1, A1, B1));
  }
}

// This code is contributed by lokeshmvs21.
Python3
MOD = 1e9 + 7

# Dp table initialized with -1
dp = [[[[-1 for x in range(190)] for y in range(10)] for z in range(21)] for w in range(21)]

# Recursive Function to find numbers
# in the range A to B such that adjacent
# digits are different and their sum is
# equal to T
def recur(i, j, k, sum, T, a):
  
    # Base case
    if i == len(a):
      
        # If current sum is equal to T
        if sum == T:
            return 1
          
        # If not equal to T
        else:
            return 0
          
    # If answer for current state is already
    # calculated then just
    # return dp[i][j][k][sum]
    if dp[i][j][k][sum] != -1:
        return dp[i][j][k][sum]
      
    # Answer initialized with zero
    ans = 0
    
    # Choosing first value
    if i == 0:
      
        # Iterating from 0 to maxvalue
        # of digit current position
        # can have
        for l in range(int(a[j])+1):
          
            # l is maximum value of digit
            if l == int(a[j]):
              
                # Calling recursive function
                # for selecting last max digit
                # for current position
                ans += recur(i+1, j+1, l, sum+l, T, a)
            else:
              
                # Calling recursive function
                # for selecting l as current
                # digit and its not max digit
                ans += recur(i+1, j, l, sum+l, T, a)
    else:
      
        # Digits taken till now were
        # all zero
        if sum == 0:
          
            # All digits can be possible
            # from 0 to 9
            for l in range(10):
              
                # Calling recursive function
                # for all digits from 0 to 9
                ans += recur(i+1, j, l, sum+l, T, a)
                
        # Already non zero digits are taken
        else:
          
            # Iterating from 0 to 9
            for l in range(10):
              
                # If max digit was taken
                # last time
                if j == i:
                  
                    # If current digit
                    # is different
                    if l <= int(a[j]) and l != k:
                      
                        # max digit taken calling
                        # recursive function
                        if l == int(a[j]):
                            ans += recur(i+1, j+1, l, sum+l, T, a)
                            
                        # Calling recursive
                        # function for non
                        # max digit
                        else:
                            ans += recur(i+1, j, l, sum+l, T, a)
                            
                # If max digit was not taken
                elif l != k:
                    ans += recur(i+1, j, l, sum+l, T, a)
    # Save and return dp value
    dp[i][j][k][sum] = ans
    return ans

# Function to find numbers
# in the range A to B such that adjacent
# digits are different and their sum is
# equal to T
def countInRange(T, A, B):
    global dp
    
    # Initializing dp array with - 1
    dp = [[[[-1 for x in range(190)] for y in range(10)] for z in range(21)] for w in range(21)]
    A -= 1
    L = str(A)
    R = str(B)
    
    # Numbers with sum of digits T from
    # 1 to L - 1
    ans1 = recur(0, 0, 0, 0, T, L)
    
    # Initializing dp array with - 1
    dp = [[[[-1 for x in range(190)] for y in range(10)] for z in range(21)] for w in range(21)]
    # Numbers with sum of digits T in
    # the range A to B
    ans2 = recur(0, 0, 0, 0, T, R)
    
    # Return the final answer
    return (ans2 - ans1 + MOD) % MOD
if __name__ == '__main__':
    #Input1
    T = 5
    A = 1
    B = 100
    
    # Function call to find numbers
    print(int(countInRange(T, A, B)))
    T = 5
    A = 1
    B =  100000000
    
    # Function call to find numbers
    print(int(countInRange(T, A, B)))
    
# This code is contributed by Potta Lokesh
C#
// C# code for the above approach
using System;
using System.Collections.Generic;

class GFG
{
  static int MOD =  1000000007;

  // Dp table initialized with -1
  static int[,,,] dp=new int[21,21,10,190];

  // Recursive Function to find numbers
  // in the range A to B such that adjacent
  // digits are different and their sum is
  // equal to T
  static int recur(int i, int j, int k, int sum, int T, string a)
  {
    // Base case
    if (i == a.Length) {

      // If current sum is equal to T
      if (sum == T)
        return 1;

      // If not equal to T
      else
        return 0;
    }

    // If answer for current state is already
    // calculated then just
    // return dp[i,j,k,sum]
    if (dp[i,j,k,sum] != -1)
      return dp[i,j,k,sum];

    // Answer initialized with zero
    int ans = 0;

    // Choosing first value
    if (i == 0) {

      // Iterating from 0 to maxvalue
      // of digit current position
      // can have
      for (int l = 0; l <= (a[j] - '0'); l++) {

        // l is maximum value of digit
        if (l ==(a[j] - '0')) {

          // Calling recursive function
          // for selecting last max digit
          // for current position
          ans += recur(i + 1, j + 1, l, sum + l, T,
                       a);
        }

        else

          // Calling recursive function
          // for selecting l as current
          // digit and its not max digit
          ans += recur(i + 1, j, l, sum + l, T, a);
      }
    }

    else {

      // Digits taken till now were
      // all zero
      if (sum == 0) {

        // All digits can be possible
        // from 0 to 9
        for (int l = 0; l <= 9; l++) {

          // Calling recursive function
          // for all digits from 0 to 9
          ans += recur(i + 1, j, l, sum + l, T, a);
        }
      }

      // Already non zero digits are taken
      else {

        // Iterating from 0 to 9
        for (int l = 0; l <= 9; l++) {

          // If max digit was taken
          // last time
          if (j == i) {

            // If current digit
            // is different
            if (l <= (a[j] - '0') && l != k) {

              // max digit taken calling
              // recursive function
              if (l == (a[j] - '0'))
                ans += recur(i + 1, j + 1, l,
                             sum + l, T, a);

              // Calling recursive
              // function for non
              // max digit
              else
                ans += recur(i + 1, j, l,
                             sum + l, T, a);
            }
          }

          // If max digit was not taken
          else if (l != k)
            ans += recur(i + 1, j, l, sum + l, T,
                         a);
        }
      }
    }

    // Save and return dp value
    return dp[i,j,k,sum] = ans;
  }

  // Function to find numbers
  // in the range A to B such that adjacent
  // digits are different and their sum is
  // equal to T
  static int countInRange(int T, int A, int B)
  {

    // Initializing dp array with - 1
    for(int i=0; i<21; i++)
    {
      for(int j=0; j<21; j++)
      {
        for(int k=0; k<10; k++)
        {
          for(int l=0; l<190; l++)
            dp[i,j,k,l]=-1;
        }
      }
    }

    A--;
    string L = A.ToString(), R = B.ToString();

    // Numbers with sum of digits T from
    // 1 to L - 1
    int ans1 = recur(0, 0, 0, 0, T, L);

    // Initializing dp array with - 1
    for(int i=0; i<21; i++)
    {
      for(int j=0; j<21; j++)
      {
        for(int k=0; k<10; k++)
        {
          for(int l=0; l<190; l++)
            dp[i,j,k,l]=-1;
        }
      }
    }

    // Numbers with sum of digits T in
    // the range 1 to R
    int ans2 = recur(0, 0, 0, 0, T, R);

    // Difference of ans2 and ans1
    // will generate answer for
    // required range
    return ans2 - ans1;
  }

  // Driver Code
  static void Main(string[] args)
  {

    // Input 1
    int T = 5, A = 1, B = 100;

    // Function Call
    Console.WriteLine(countInRange(T, A, B));

    // Input 2
    int T1 = 5, A1 = 1, B1 = 100000000;

    // Function Call
    Console.WriteLine(countInRange(T1, A1, B1));
  }
}
JavaScript
// Javascript code to implement the approach
let MOD = 1e9 + 7;

// Dp table initialized with -1
//let dp[21][21][10][190];
let dp = new Array(21);

function memset(dp, x)
{
    for(let i = 0; i < 21; i++)
    {
        dp[i] = new Array(21);
        for(let j = 0; j < 21; j++)
        {
            dp[i][j] = new Array(10);
            for(let k = 0; k < 10; k++)
                dp[i][j][k] = new Array(190).fill(-1);
        }
    }
}

// Recursive Function to find numbers
// in the range A to B such that adjacent
// digits are different and their sum is
// equal to T
function recur(i, j, k, sum, T, a)
{
    // Base case
    if (i == a.length) {

        // If current sum is equal to T
        if (sum == T)
            return 1;

        // If not equal to T
        else
            return 0;
    }

    // If answer for current state is already
    // calculated then just
    // return dp[i][j][k][sum]
    if (dp[i][j][k][sum] != -1)
        return dp[i][j][k][sum];

    // Answer initialized with zero
    let ans = 0;

    // Choosing first value
    if (i == 0) {

        // Iterating from 0 to maxvalue
        // of digit current position
        // can have
        for (let l = 0; l <= parseInt(a[j]); l++) {

            // l is maximum value of digit
            if (l == parseInt(a[j])) {

                // Calling recursive function
                // for selecting last max digit
                // for current position
                ans += recur(i + 1, j + 1, l, sum + l, T,
                             a);
            }

            else

                // Calling recursive function
                // for selecting l as current
                // digit and its not max digit
                ans += recur(i + 1, j, l, sum + l, T, a);
        }
    }

    else {

        // Digits taken till now were
        // all zero
        if (sum == 0) {

            // All digits can be possible
            // from 0 to 9
            for (let l = 0; l <= 9; l++) {

                // Calling recursive function
                // for all digits from 0 to 9
                ans += recur(i + 1, j, l, sum + l, T, a);
            }
        }

        // Already non zero digits are taken
        else {

            // Iterating from 0 to 9
            for (let l = 0; l <= 9; l++) {

                // If max digit was taken
                // last time
                if (j == i) {

                    // If current digit
                    // is different
                    if (l <= parseInt(a[j]) && l != k) {

                        // max digit taken calling
                        // recursive function
                        if (l == parseInt(a[j]))
                            ans += recur(i + 1, j + 1, l,
                                         sum + l, T, a);

                        // Calling recursive
                        // function for non
                        // max digit
                        else
                            ans += recur(i + 1, j, l,
                                         sum + l, T, a);
                    }
                }

                // If max digit was not taken
                else if (l != k)
                    ans += recur(i + 1, j, l, sum + l, T,
                                 a);
            }
        }
    }

    // Save and return dp value
    return dp[i][j][k][sum] = ans;
}

// Function to find numbers
// in the range A to B such that adjacent
// digits are different and their sum is
// equal to T
function countInRange(T, A, B)
{

    // Initializing dp array with - 1
    memset(dp, -1);

    A--;
    let L = A.toString(), R = B.toString();

    // Numbers with sum of digits T from
    // 1 to L - 1
    let ans1 = recur(0, 0, 0, 0, T, L);

    // Initializing dp array with - 1
    memset(dp, -1);

    // Numbers with sum of digits T in
    // the range 1 to R
    let ans2 = recur(0, 0, 0, 0, T, R);

    // Difference of ans2 and ans1
    // will generate answer for
    // required range
    return ans2 - ans1;
}

// Driver Code

    // Input 1
let T = 5, A = 1, B = 100;
// Function Call
console.log(countInRange(T, A, B));

// Input 2
let T1 = 5, A1 = 1, B1 = 100000000;

// Function Call
console.log(countInRange(T1, A1, B1));

// This code is contributed by ritaagarwal.

Output
6
74

Time Complexity: O(N2 * M * K2)  
Auxiliary Space: O(N2 * M * K)

Related Articles:


Next Article

Similar Reads