Given a positive integer N, the task is to find the number of all N-digit numbers whose adjacent digits have equal Greatest Common Divisor(GCD).
Examples:
Input: N = 2
Output: 90
Explanation:
All 2-digit numbers satisfy the condition as there is only one pair of digits and there are 90 2-digit numbers.
Input: N = 3
Output: 457
Naive Approach: The simplest approach to solve the given problem is to generate all possible N-digit numbers and count those numbers whose adjacent digits have equal GCD. After checking for all the numbers, print the value of the count as the resultant total count of numbers.
Time Complexity: O(N *10N)
Auxiliary Space: O(1)
Efficient Approach: The above approach can also be optimized by using Dynamic Programming because the above problem has Overlapping subproblems and an Optimal substructure. The subproblems can be stored in dp[][][] table memoization where dp[index][prev][gcd] stores the answer from the indexth position till the end, where prev is used to store the previous digit of the number and gcd is the GCD between existing adjacent digits in the number. Follow the steps below to solve the problem:
- Initialize a global multidimensional array dp[100][10][10] with all values as -1 that stores the result of each recursive call.
- Define a recursive function, say countOfNumbers(index, prev, gcd, N) and performing the following steps:
- If the value of the index as (N + 1), then return 1 as a valid N-digit number has been formed.
- If the result of the state dp[index][prev][gcd] is already computed, return this value dp[index][prev][gcd].
- If the current index is 1, then any digit from [1- 9] can be placed.
- If the current index is greater than 1, any digit from [0-9] can be placed.
- If the index is greater than 2, a digit can be placed if the gcd of the current digit and the previous digit is equal to the GCD of already existing adjacent digits.
- After making a valid placement of digits, recursively call the countOfNumbers function for (index + 1).
- Return the sum of all possible valid placements of digits as the answer.
- Print the value returned by the function countOfNumbers(1, 0, 0, N) as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[100][10][10];
int countOfNumbers( int index, int prev,
int gcd, int N)
{
if (index == N + 1)
return 1;
int & val = dp[index][prev][gcd];
if (val != -1)
return val;
val = 0;
if (index == 1) {
for ( int digit = (N == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += countOfNumbers(
index + 1,
digit, gcd, N);
}
}
else if (index == 2) {
for ( int digit = 0;
digit <= 9; ++digit) {
val += countOfNumbers(
index + 1, digit,
__gcd(prev, digit), N);
}
}
else {
for ( int digit = 0;
digit <= 9; ++digit) {
if (__gcd(digit, prev) == gcd) {
val += countOfNumbers(
index + 1, digit, gcd, N);
}
}
}
return val;
}
int countNumbers( int N)
{
memset (dp, -1, sizeof dp);
return countOfNumbers(1, 0, 0, N);
}
int main()
{
int N = 2;
cout << countNumbers(N);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int [][][] dp = new int [ 100 ][ 10 ][ 10 ];
static int _gcd( int a, int b)
{
if (a == 0 )
return b;
if (b == 0 )
return a;
if (a == b)
return a;
if (a > b)
return _gcd(a-b, b);
return _gcd(a, b-a);
}
static int countOfNumbers( int index, int prev,
int gcd, int N)
{
if (index == N + 1 )
return 1 ;
int val = dp[index][prev][gcd];
if (val != - 1 )
return val;
val = 0 ;
if (index == 1 ) {
for ( int digit = (N == 1 ? 0 : 1 );
digit <= 9 ;
++digit) {
val += countOfNumbers(
index + 1 ,
digit, gcd, N);
}
}
else if (index == 2 ) {
for ( int digit = 0 ;
digit <= 9 ; ++digit) {
val += countOfNumbers(
index + 1 , digit,
_gcd(prev, digit), N);
}
}
else {
for ( int digit = 0 ;
digit <= 9 ; ++digit) {
if (_gcd(digit, prev) == gcd) {
val += countOfNumbers(
index + 1 , digit, gcd, N);
}
}
}
return val;
}
static int countNumbers( int N)
{
int i, j, k;
for (i = 0 ; i < 100 ; i++)
{
for (j = 0 ; j < 10 ; j++)
{
for (k = 0 ; k < 10 ; k++)
{
dp[i][j][k] = - 1 ;
}
}
}
return countOfNumbers( 1 , 0 , 0 , N);
}
public static void main(String[] args)
{
int N = 2 ;
System.out.println(countNumbers(N));
}
}
|
Python3
dp = [[[ - 1 for i in range ( 10 )]
for j in range ( 10 )]
for k in range ( 100 )]
from math import gcd
def countOfNumbers(index, prev, gcd1, N):
if (index = = N + 1 ):
return 1
val = dp[index][prev][gcd1]
if (val ! = - 1 ):
return val
val = 0
if (index = = 1 ):
digit = 0 if N = = 1 else 1
while (digit < = 9 ):
val + = countOfNumbers(index + 1 ,
digit, gcd1, N)
digit + = 1
elif (index = = 2 ):
for digit in range ( 10 ):
val + = countOfNumbers(index + 1 , digit,
gcd(prev, digit), N)
else :
for digit in range ( 10 ):
if (gcd(digit, prev) = = gcd):
val + = countOfNumbers(index + 1 , digit,
gcd1, N)
return val
def countNumbers(N):
return countOfNumbers( 1 , 0 , 0 , N)
if __name__ = = '__main__' :
N = 2
print (countNumbers(N))
|
C#
using System;
public class GFG
{
static int [,,] dp = new int [100, 10, 10];
static int _gcd( int a, int b)
{
if (a == 0)
return b;
if (b == 0)
return a;
if (a == b)
return a;
if (a > b)
return _gcd(a-b, b);
return _gcd(a, b-a);
}
static int countOfNumbers( int index, int prev,
int gcd, int N)
{
if (index == N + 1)
return 1;
int val = dp[index,prev,gcd];
if (val != -1)
return val;
val = 0;
if (index == 1) {
for ( int digit = (N == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += countOfNumbers(
index + 1,
digit, gcd, N);
}
}
else if (index == 2) {
for ( int digit = 0;
digit <= 9; ++digit) {
val += countOfNumbers(
index + 1, digit,
_gcd(prev, digit), N);
}
}
else {
for ( int digit = 0;
digit <= 9; ++digit) {
if (_gcd(digit, prev) == gcd) {
val += countOfNumbers(
index + 1, digit, gcd, N);
}
}
}
return val;
}
static int countNumbers( int N)
{
int i, j, k;
for (i = 0; i < 100; i++)
{
for (j = 0; j < 10; j++)
{
for (k = 0; k < 10; k++)
{
dp[i,j,k] = -1;
}
}
}
return countOfNumbers(1, 0, 0, N);
}
static public void Main ()
{
int N = 2;
Console.Write(countNumbers(N));
}
}
|
Javascript
<script>
let dp = new Array(100).fill(0).map(() => new Array(10).fill(0).map(() => new Array(10).fill(-1)));
function countOfNumbers(index, prev, gcd, N)
{
if (index == N + 1)
return 1;
let val = dp[index][prev][gcd];
if (val != -1)
return val;
val = 0;
if (index == 1) {
for (let digit = (N == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += countOfNumbers(
index + 1,
digit, gcd, N);
}
}
else if (index == 2) {
for (let digit = 0; digit <= 9; ++digit) {
val += countOfNumbers(
index + 1, digit,
__gcd(prev, digit), N);
}
}
else {
for (let digit = 0; digit <= 9; ++digit) {
if (__gcd(digit, prev) == gcd) {
val += countOfNumbers(
index + 1, digit, gcd, N);
}
}
}
return val;
}
function countNumbers(N)
{
return countOfNumbers(1, 0, 0, N);
}
function __gcd(a, b)
{
if (b == 0)
return a;
return __gcd(b, a % b);
}
let N = 2;
document.write(countNumbers(N));
</script>
|
Time Complexity: O(N * 1000)
Auxiliary Space: O(N * 10 * 10)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
10 Aug, 2021
Like Article
Save Article