Count ways to generate N digit number such that its every digit divisible by previous digit
Last Updated :
16 May, 2023
Given a number N, the task is to count the number of ways to create an N digit number from digits 1 to 9 such that every digit is divisible by its previous digit that is if the number is represented by an array of digits A then A[i + 1] % A[i] == 0. print the answer modulo 109 + 7.
Examples:
Input: N = 2
Output: 23
Explanation: For N = 2 possible answers are 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 24, 26, 28, 33, 36, 39, 44, 48, 55, 66, 77, 88, and 99.
Input: N = 3
Output: 44
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(9N)
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] represents the number of ways of creating a number of size i and j is its previous digit taken.
- 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 by storing 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 two parameters representing ith position to be filled and j representing the last digit taken.
- Call the recursive function for choosing all digits from 1 to 9.
- Base case if all positions filled return 1.
- Create a 2d array of dp[N][10] initially filled with -1.
- If the answer for a particular state is computed then save it in dp[i][j].
- If the answer for a particular state is already computed then just return dp[i][j].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int dp[100001][10];
int recur( int i, int j, int N)
{
if (i == N) {
return 1;
}
if (dp[i][j] != -1)
return dp[i][j];
int ans = 0;
if (i == 0) {
for ( int digit = 1; digit <= 9; digit++) {
ans = (ans + recur(i + 1, digit, N)) % MOD;
}
}
else {
for ( int digit = 1; digit <= 9; digit++) {
if (digit % j == 0)
ans = (ans + recur(i + 1, digit, N)) % MOD;
}
}
return dp[i][j] = ans;
}
int countWays( int N)
{
memset (dp, -1, sizeof (dp));
int ans = recur(0, 0, N);
return ans;
}
int main()
{
int N = 2;
cout << countWays(N) << endl;
int N1 = 3;
cout << countWays(N1) << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static final int MOD = ( int )1e9 + 7 ;
static int [][] dp;
static int recur( int i, int j, int N)
{
if (i == N) {
return 1 ;
}
if (dp[i][j] != - 1 ) {
return dp[i][j];
}
int ans = 0 ;
if (i == 0 ) {
for ( int digit = 1 ; digit <= 9 ; digit++) {
ans = (ans + recur(i + 1 , digit, N)) % MOD;
}
}
else {
for ( int digit = 1 ; digit <= 9 ; digit++) {
if (digit % j == 0 ) {
ans = (ans + recur(i + 1 , digit, N))
% MOD;
}
}
}
return dp[i][j] = ans;
}
static int countWays( int N)
{
dp = new int [N + 1 ][ 10 ];
for ( int [] row : dp) {
Arrays.fill(row, - 1 );
}
int ans = recur( 0 , 0 , N);
return ans;
}
public static void main(String[] args)
{
int N = 2 ;
System.out.println(countWays(N));
int N1 = 3 ;
System.out.println(countWays(N1));
}
}
|
Python3
MOD = 1e9 + 7
dp = [[ - 1 for j in range ( 10 )] for i in range ( 100001 )]
def recur(i, j, N):
if i = = N:
return 1
if dp[i][j] ! = - 1 :
return dp[i][j]
ans = 0
if i = = 0 :
for digit in range ( 1 , 10 ):
ans = (ans + recur(i + 1 , digit, N)) % MOD
else :
for digit in range ( 1 , 10 ):
if digit % j = = 0 :
ans = (ans + recur(i + 1 , digit, N)) % MOD
dp[i][j] = ans
return ans
def count_ways(N):
ans = recur( 0 , 0 , N)
return ans
N = 2
print (count_ways(N))
N1 = 3
dp = [[ - 1 for j in range ( 10 )] for i in range ( 100001 )]
print (count_ways(N1))
|
C#
using System;
public class GFG {
static readonly int MOD = ( int )1e9 + 7;
static int [, ] dp;
static int recur( int i, int j, int N)
{
if (i == N) {
return 1;
}
if (dp[i, j] != -1) {
return dp[i, j];
}
int ans = 0;
if (i == 0) {
for ( int digit = 1; digit <= 9; digit++) {
ans = (ans + recur(i + 1, digit, N)) % MOD;
}
}
else {
for ( int digit = 1; digit <= 9; digit++) {
if (digit % j == 0) {
ans = (ans + recur(i + 1, digit, N))
% MOD;
}
}
}
return dp[i, j] = ans;
}
static int countWays( int N)
{
dp = new int [N + 1, 10];
for ( int i = 0; i <= N; i++) {
for ( int j = 0; j <= 9; j++) {
dp[i, j] = -1;
}
}
int ans = recur(0, 0, N);
return ans;
}
static public void Main()
{
int N = 2;
Console.WriteLine(countWays(N));
int N1 = 3;
Console.WriteLine(countWays(N1));
}
}
|
Javascript
const MOD = 1e9 + 7;
let dp= new Array(1000001);
for (let i = 0; i < 1000001; i++)
dp[i] = new Array(10).fill(-1);
function recur( i, j, N)
{
if (i == N) {
return 1;
}
if (dp[i][j] != -1)
return dp[i][j];
let ans = 0;
if (i == 0) {
for (let digit = 1; digit <= 9; digit++) {
ans = (ans + recur(i + 1, digit, N)) % MOD;
}
}
else {
for (let digit = 1; digit <= 9; digit++) {
if (digit % j == 0)
ans = (ans + recur(i + 1, digit, N)) % MOD;
}
}
return dp[i][j] = ans;
}
function countWays( N)
{
for (let i = 0; i < 100001; i++)
{
for (let j = 0; j < 10; j++)
dp[i][j]=-1;
}
let ans = recur(0, 0, N);
return ans;
}
let N = 2;
console.log(countWays(N));
let N1 = 3;
console.log(countWays(N1));
|
Time Complexity: O(N)
Auxiliary Space: O(N)
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 + memorization(top-down) because memorization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a table to store the solution of the subproblems.
- Initialize the table with base cases
- Fill up the table iteratively
- Return the final solution
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int countWays( int N)
{
vector<vector< int >> dp(N+1, vector< int >(10, 0));
for ( int j = 1; j <= 9; j++) {
dp[1][j] = 1;
}
for ( int i = 2; i <= N; i++) {
for ( int j = 1; j <= 9; j++) {
for ( int k = j; k <= 9; k++) {
if (k % j == 0) {
dp[i][j] = (dp[i][j] + dp[i-1][k]) % MOD;
}
}
}
}
int ans = 0;
for ( int j = 1; j <= 9; j++) {
ans = (ans + dp[N][j]) % MOD;
}
return ans;
}
int main()
{
int N = 2;
cout << countWays(N) << endl;
int N1 = 3;
cout << countWays(N1) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
static final int MOD = ( int ) 1e9 + 7 ;
static int countWays( int N) {
int [][] dp = new int [N + 1 ][ 10 ];
for ( int j = 1 ; j <= 9 ; j++) {
dp[ 1 ][j] = 1 ;
}
for ( int i = 2 ; i <= N; i++) {
for ( int j = 1 ; j <= 9 ; j++) {
for ( int k = j; k <= 9 ; k++) {
if (k % j == 0 ) {
dp[i][j] = (dp[i][j] + dp[i - 1 ][k]) % MOD;
}
}
}
}
int ans = 0 ;
for ( int j = 1 ; j <= 9 ; j++) {
ans = (ans + dp[N][j]) % MOD;
}
return ans;
}
public static void main (String[] args) {
int N = 2 ;
System.out.println(countWays(N));
int N1 = 3 ;
System.out.println(countWays(N1));
}
}
|
Python3
MOD = int ( 1e9 + 7 )
def countWays(N: int ) - > int :
dp = [[ 0 ] * 10 for _ in range (N + 1 )]
for j in range ( 1 , 10 ):
dp[ 1 ][j] = 1
for i in range ( 2 , N + 1 ):
for j in range ( 1 , 10 ):
for k in range (j, 10 ):
if k % j = = 0 :
dp[i][j] = (dp[i][j] + dp[i - 1 ][k]) % MOD
ans = 0
for j in range ( 1 , 10 ):
ans = (ans + dp[N][j]) % MOD
return ans
if __name__ = = '__main__' :
N = 2
print (countWays(N))
N1 = 3
print (countWays(N1))
|
Javascript
const MOD = 1e9 + 7;
function countWays(N) {
let dp = new Array(N + 1);
for (let i = 0; i <= N; i++) {
dp[i] = new Array(10).fill(0);
}
for (let j = 1; j <= 9; j++) {
dp[1][j] = 1;
}
for (let i = 2; i <= N; i++) {
for (let j = 1; j <= 9; j++) {
for (let k = j; k <= 9; k++) {
if (k % j === 0) {
dp[i][j] = (dp[i][j] + dp[i-1][k]) % MOD;
}
}
}
}
let ans = 0;
for (let j = 1; j <= 9; j++) {
ans = (ans + dp[N][j]) % MOD;
}
return ans;
}
let N = 2;
console.log(countWays(N));
let N1 = 3;
console.log(countWays(N1));
|
C#
using System;
using System.Collections.Generic;
class GFG {
const int MOD = 1000000007;
static int countWays( int N)
{
List<List< int > > dp = new List<List< int > >();
for ( int i = 0; i <= N; i++) {
dp.Add( new List< int >());
for ( int j = 0; j < 10; j++) {
dp[i].Add(0);
}
}
for ( int j = 1; j <= 9; j++) {
dp[1][j] = 1;
}
for ( int i = 2; i <= N; i++) {
for ( int j = 1; j <= 9; j++) {
for ( int k = j; k <= 9; k++) {
if (k % j == 0) {
dp[i][j] = (dp[i][j] + dp[i - 1][k])
% MOD;
}
}
}
}
int ans = 0;
for ( int j = 1; j <= 9; j++) {
ans = (ans + dp[N][j]) % MOD;
}
return ans;
}
static void Main()
{
int N = 2;
Console.WriteLine(countWays(N));
int N1 = 3;
Console.WriteLine(countWays(N1));
}
}
|
Time Complexity : O(N)
Auxiliary Space: O(N)
Related Articles:
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...