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++ 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 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. |
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# 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 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. |
6 74
Time Complexity: O(N2 * M * K2)
Auxiliary Space: O(N2 * M * K)
Related Articles: