Smallest number with given sum of digits and sum of square of digits
Given the sum of digits a and sum of the square of digits b . Find the smallest number with the given sum of digits and the sum of the square of digits. The number should not contain more than 100 digits. Print -1 if no such number exists or if the number of digits is more than 100.
Examples:
Input : a = 18, b = 162
Output : 99
Explanation : 99 is the smallest possible number whose sum of digits = 9 + 9 = 18 and sum of squares of digits is 92+92 = 162.
Input : a = 12, b = 9
Output : -1
Approach:
Since the smallest number can be of 100 digits, it cannot be stored. Hence the first step to solve it will be to find the minimum number of digits which can give us the sum of digits as and sum of the square of digits as . To find the minimum number of digits, we can use Dynamic Programming. DP[a][b] signifies the minimum number of digits in a number whose sum of the digits will be and sum of the square of digits will be . If there does not exist any such number then DP[a][b] will be -1.
Since the number cannot exceed 100 digits, DP array will be of size 101*8101. Iterate for every digit, and try all possible combination of digits which gives us the sum of digits as and sum of the square of digits as . Store the minimum number of digits in DP[a][b] using the below recurrence relation:
DP[a][b] = min( minimumNumberOfDigits(a – i, b – (i * i)) + 1 )
where 1<=i<=9
After getting the minimum number of digits, find the digits. To find the digits, check for all combinations and print those digits which satisfies the condition below:
1 + dp[a – i][b – i * i] == dp[a][b]
where 1<=i<=9
If the condition above is met by any of i, reduce a by i and b by i*i and break. Keep on repeating the above process to find all the digits till a is 0 and b is 0.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[901][8101];
int minimumNumberOfDigits( int a, int b)
{
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100)
return -1;
if (a == 0 && b == 0)
return 0;
if (dp[a][b] != -1)
return dp[a][b];
int ans = 101;
for ( int i = 9; i >= 1; i--) {
int k = minimumNumberOfDigits(a - i, b - (i * i));
if (k != -1)
ans = min(ans, k + 1);
}
return dp[a][b] = ans;
}
void printSmallestNumber( int a, int b)
{
memset (dp, -1, sizeof (dp));
dp[0][0] = 0;
int k = minimumNumberOfDigits(a, b);
if (k == -1 || k > 100)
cout << "-1" ;
else {
while (a > 0 && b > 0) {
for ( int i = 1; i <= 9; i++) {
if (a >= i && b >= i * i
&& 1 + dp[a - i][b - i * i] == dp[a][b]) {
cout << i;
a -= i;
b -= i * i;
break ;
}
}
}
}
}
int main()
{
int a = 18, b = 162;
printSmallestNumber(a, b);
}
|
C
#include <stdio.h>
#include <string.h>
int min( int num1, int num2)
{
return (num1 > num2) ? num2 : num1;
}
int dp[901][8101];
int minimumNumberOfDigits( int a, int b)
{
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100)
return -1;
if (a == 0 && b == 0)
return 0;
if (dp[a][b] != -1)
return dp[a][b];
int ans = 101;
for ( int i = 9; i >= 1; i--) {
int k = minimumNumberOfDigits(a - i, b - (i * i));
if (k != -1)
ans = min(ans, k + 1);
}
return dp[a][b] = ans;
}
void printSmallestNumber( int a, int b)
{
memset (dp, -1, sizeof (dp));
dp[0][0] = 0;
int k = minimumNumberOfDigits(a, b);
if (k == -1 || k > 100)
printf ( "-1" );
else {
while (a > 0 && b > 0) {
for ( int i = 1; i <= 9; i++) {
if (a >= i && b >= i * i
&& 1 + dp[a - i][b - i * i]
== dp[a][b]) {
printf ( "%d" , i);
a -= i;
b -= i * i;
break ;
}
}
}
}
}
int main()
{
int a = 18, b = 162;
printSmallestNumber(a, b);
}
|
Java
import java.util.Arrays;
class GFG {
static int dp[][] = new int [ 901 ][ 8101 ];
static int minimumNumberOfDigits( int a, int b) {
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100 ) {
return - 1 ;
}
if (a == 0 && b == 0 ) {
return 0 ;
}
if (dp[a][b] != - 1 ) {
return dp[a][b];
}
int ans = 101 ;
for ( int i = 9 ; i >= 1 ; i--) {
int k = minimumNumberOfDigits(a - i, b - (i * i));
if (k != - 1 ) {
ans = Math.min(ans, k + 1 );
}
}
return dp[a][b] = ans;
}
static void printSmallestNumber( int a, int b) {
for ( int [] row : dp) {
Arrays.fill(row, - 1 );
}
dp[ 0 ][ 0 ] = 0 ;
int k = minimumNumberOfDigits(a, b);
if (k == - 1 || k > 100 ) {
System.out.println( "-1" );
} else {
while (a > 0 && b > 0 ) {
for ( int i = 1 ; i <= 9 ; i++) {
if (a >= i && b >= i * i
&& 1 + dp[a - i][b - i * i] == dp[a][b]) {
System.out.print(i);
a -= i;
b -= i * i;
break ;
}
}
}
}
}
public static void main(String args[]) {
int a = 18 , b = 162 ;
printSmallestNumber(a, b);
}
}
|
Python3
dp = [[ - 1 for i in range ( 8101 )] for i in range ( 901 )]
def minimumNumberOfDigits(a,b):
if (a > b or a < 0 or b < 0 or a > 900 or b > 8100 ):
return - 1
if (a = = 0 and b = = 0 ):
return 0
if (dp[a][b] ! = - 1 ):
return dp[a][b]
ans = 101
for i in range ( 9 , 0 , - 1 ):
k = minimumNumberOfDigits(a - i, b - (i * i))
if (k ! = - 1 ):
ans = min (ans, k + 1 )
dp[a][b] = ans
return ans
def printSmallestNumber(a,b):
for i in range ( 901 ):
for j in range ( 8101 ):
dp[i][j] = - 1
dp[ 0 ][ 0 ] = 0
k = minimumNumberOfDigits(a, b)
if (k = = - 1 or k > 100 ):
print ( - 1 ,end = '')
else :
while (a > 0 and b > 0 ):
for i in range ( 1 , 10 ):
if (a > = i and b > = i * i and
1 + dp[a - i][b - i * i] = = dp[a][b]):
print (i,end = '')
a - = i
b - = i * i
break
if __name__ = = '__main__' :
a = 18
b = 162
printSmallestNumber(a,b)
|
C#
using System;
public class GFG {
static int [,]dp = new int [901,8101];
static int minimumNumberOfDigits( int a, int b) {
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100) {
return -1;
}
if (a == 0 && b == 0) {
return 0;
}
if (dp[a,b] != -1) {
return dp[a,b];
}
int ans = 101;
for ( int i = 9; i >= 1; i--) {
int k = minimumNumberOfDigits(a - i, b - (i * i));
if (k != -1) {
ans = Math.Min(ans, k + 1);
}
}
return dp[a,b] = ans;
}
static void printSmallestNumber( int a, int b) {
for ( int i = 0; i < dp.GetLength(0); i++)
for ( int j = 0; j < dp.GetLength(1); j++)
dp[i, j] = -1;
dp[0,0] = 0;
int k = minimumNumberOfDigits(a, b);
if (k == -1 || k > 100) {
Console.WriteLine( "-1" );
} else {
while (a > 0 && b > 0) {
for ( int i = 1; i <= 9; i++) {
if (a >= i && b >= i * i
&& 1 + dp[a - i,b - i * i] == dp[a,b]) {
Console.Write(i);
a -= i;
b -= i * i;
break ;
}
}
}
}
}
public static void Main() {
int a = 18, b = 162;
printSmallestNumber(a, b);
}
}
|
Javascript
<script>
dp = new Array(901).fill(-1).map(() =>
new Array(8101).fill(-1));;
function minimumNumberOfDigits(a, b)
{
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100)
return -1;
if (a == 0 && b == 0)
return 0;
if (dp[a][b] != -1)
return dp[a][b];
var ans = 101;
for ( var i = 9; i >= 1; i--) {
var k = minimumNumberOfDigits(a - i, b - (i * i));
if (k != -1)
ans = Math.min(ans, k + 1);
}
return dp[a][b] = ans;
}
function printSmallestNumber(a, b)
{
dp[0][0] = 0;
var k = minimumNumberOfDigits(a, b);
if (k == -1 || k > 100)
document.write( "-1" );
else {
while (a > 0 && b > 0) {
for ( var i = 1; i <= 9; i++) {
if (a >= i && b >= i * i &&
1 + dp[a - i][b - i * i] == dp[a][b]) {
document.write( i);
a -= i;
b -= i * i;
break ;
}
}
}
}
}
var a = 18, b = 162;
printSmallestNumber(a,b);
</script>
|
Time Complexity : O(900*8100*9)
Auxiliary Space : O(900*8100)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Implementation :
C++
#include <cstring>
#include <iostream>
using namespace std;
int dp[901][8101];
int minimumNumberOfDigits( int a, int b)
{
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100)
return -1;
if (a == 0 && b == 0)
return 0;
memset (dp, -1, sizeof (dp));
dp[0][0] = 0;
for ( int i = 0; i <= a; i++) {
for ( int j = 0; j <= b; j++) {
if (dp[i][j] == -1)
continue ;
for ( int digit = 1; digit <= 9; digit++) {
if (i + digit <= a
&& j + digit * digit <= b) {
int new_a = i + digit;
int new_b = j + digit * digit;
if (dp[new_a][new_b] == -1
|| dp[new_a][new_b] > dp[i][j] + 1)
dp[new_a][new_b] = dp[i][j] + 1;
}
}
}
}
return dp[a][b];
}
void printSmallestNumber( int a, int b)
{
int k = minimumNumberOfDigits(a, b);
if (k == -1 || k > 100)
cout << "-1" ;
else {
while (a > 0 && b > 0) {
for ( int digit = 1; digit <= 9; digit++) {
if (a >= digit && b >= digit * digit
&& dp[a][b]
== dp[a - digit]
[b - digit * digit]
+ 1) {
cout << digit;
a -= digit;
b -= digit * digit;
break ;
}
}
}
}
}
int main()
{
int a = 18, b = 162;
printSmallestNumber(a, b);
return 0;
}
|
Java
import java.util.Arrays;
public class Main {
static int [][] dp = new int [ 901 ][ 8101 ];
static int minimumNumberOfDigits( int a, int b)
{
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100 )
return - 1 ;
if (a == 0 && b == 0 )
return 0 ;
for ( int i = 0 ; i <= 900 ; i++) {
Arrays.fill(dp[i], - 1 );
}
dp[ 0 ][ 0 ] = 0 ;
for ( int i = 0 ; i <= a; i++) {
for ( int j = 0 ; j <= b; j++) {
if (dp[i][j] == - 1 )
continue ;
for ( int digit = 1 ; digit <= 9 ; digit++) {
if (i + digit <= a
&& j + digit * digit <= b) {
int new_a = i + digit;
int new_b = j + digit * digit;
if (dp[new_a][new_b] == - 1
|| dp[new_a][new_b]
> dp[i][j] + 1 )
dp[new_a][new_b] = dp[i][j] + 1 ;
}
}
}
}
return dp[a][b];
}
static void printSmallestNumber( int a, int b)
{
int k = minimumNumberOfDigits(a, b);
if (k == - 1 || k > 100 )
System.out.print( "-1" );
else {
while (a > 0 && b > 0 ) {
for ( int digit = 1 ; digit <= 9 ; digit++) {
if (a >= digit && b >= digit * digit
&& dp[a][b]
== dp[a - digit]
[b - digit * digit]
+ 1 ) {
System.out.print(digit);
a -= digit;
b -= digit * digit;
break ;
}
}
}
}
}
public static void main(String[] args)
{
int a = 18 , b = 162 ;
printSmallestNumber(a, b);
}
}
|
Python3
def minimumNumberOfDigits(a, b):
if a > b or a < 0 or b < 0 or a > 900 or b > 8100 :
return - 1
if a = = 0 and b = = 0 :
return 0
dp = [[ - 1 for _ in range ( 8101 )] for _ in range ( 901 )]
dp[ 0 ][ 0 ] = 0
for i in range (a + 1 ):
for j in range (b + 1 ):
if dp[i][j] = = - 1 :
continue
for digit in range ( 1 , 10 ):
if i + digit < = a and j + digit * digit < = b:
new_a = i + digit
new_b = j + digit * digit
if dp[new_a][new_b] = = - 1 or dp[new_a][new_b] > dp[i][j] + 1 :
dp[new_a][new_b] = dp[i][j] + 1
return dp
def printSmallestNumber(a, b, dp):
k = dp[a][b]
if k = = - 1 or k > 100 :
print ( "-1" )
else :
while a > 0 and b > 0 :
for digit in range ( 1 , 10 ):
if a > = digit and b > = digit * digit and dp[a][b] = = dp[a - digit][b - digit * digit] + 1 :
print (digit, end = "")
a - = digit
b - = digit * digit
break
if __name__ = = "__main__" :
a = 18
b = 162
dp = minimumNumberOfDigits(a, b)
printSmallestNumber(a, b, dp)
|
C#
using System;
class Program {
static int [, ] dp = new int [901, 8101];
static int MinimumNumberOfDigits( int a, int b)
{
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100)
return -1;
if (a == 0 && b == 0)
return 0;
for ( int i = 0; i < 901; i++) {
for ( int j = 0; j < 8101; j++) {
dp[i, j] = -1;
}
}
dp[0, 0] = 0;
for ( int i = 0; i <= a; i++) {
for ( int j = 0; j <= b; j++) {
if (dp[i, j] == -1)
continue ;
for ( int digit = 1; digit <= 9; digit++) {
if (i + digit <= a
&& j + digit * digit <= b) {
int newA = i + digit;
int newB = j + digit * digit;
if (dp[newA, newB] == -1
|| dp[newA, newB]
> dp[i, j] + 1)
dp[newA, newB] = dp[i, j] + 1;
}
}
}
}
return dp[a, b];
}
static void PrintSmallestNumber( int a, int b)
{
int k = MinimumNumberOfDigits(a, b);
if (k == -1 || k > 100) {
Console.WriteLine( "-1" );
}
else {
while (a > 0 && b > 0) {
for ( int digit = 1; digit <= 9; digit++) {
if (a >= digit && b >= digit * digit
&& dp[a, b]
== dp[a - digit,
b - digit * digit]
+ 1) {
Console.Write(digit);
a -= digit;
b -= digit * digit;
break ;
}
}
}
}
}
static void Main( string [] args)
{
int a = 18, b = 162;
PrintSmallestNumber(a, b);
}
}
|
Javascript
let dp = new Array(901);
for (let i = 0; i <= 900; i++) {
dp[i] = new Array(8101).fill(-1);
}
function minimumNumberOfDigits(a, b) {
if (a > b || a < 0 || b < 0 || a > 900 || b > 8100)
return -1;
if (a === 0 && b === 0)
return 0;
dp[0][0] = 0;
for (let i = 0; i <= a; i++) {
for (let j = 0; j <= b; j++) {
if (dp[i][j] === -1)
continue ;
for (let digit = 1; digit <= 9; digit++) {
if (i + digit <= a && j + digit * digit <= b) {
let new_a = i + digit;
let new_b = j + digit * digit;
if (dp[new_a][new_b] === -1 || dp[new_a][new_b] > dp[i][j] + 1)
dp[new_a][new_b] = dp[i][j] + 1;
}
}
}
}
return dp[a][b];
}
function printSmallestNumber(a, b) {
let k = minimumNumberOfDigits(a, b);
let result = '' ;
if (k === -1 || k > 100) {
console.log( "-1" );
} else {
while (a > 0 && b > 0) {
for (let digit = 1; digit <= 9; digit++) {
if (a >= digit && b >= digit * digit && dp[a][b] === dp[a - digit][b - digit * digit] + 1) {
result += digit;
a -= digit;
b -= digit * digit;
break ;
}
}
}
console.log(result);
}
}
const a = 18;
const b = 162;
printSmallestNumber(a, b);
|
Time Complexity : O(900*8100*9)
Auxiliary Space : O(900*8100)
Last Updated :
16 Nov, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...