Given two numbers N and K, the task is to count the number of all possible arrays of size N such that each element is a positive integer less than or equal to K and is either a multiple or a divisor of its neighbours. Since the answer can be large, print it modulo 109 + 7.
Examples:
Input: N = 2, K = 3
Output: 7
Explanation: All the possible arrays are – { {1, 2}, {2, 1}, {1, 3}, {3, 1}, {1, 1}, {2, 2}, {3, 3} }Input: N = 5, K = 4
Output: 380
Naive Approach: The simplest approach is to find all combinations of arrays of size N where each element is less than or equal to ‘K’, and for each combination check if adjacent elements are multiples of each other or not.
Time Complexity: O(KN * N)
Auxiliary Space: O(N)
Efficient Approach: The above approach can also be optimized by using Dynamic Programming because of its overlapping subproblems and optimal substructure property using the following observation:
The subproblems can be stored in dp[][] table using memoization where dp[i][prev] stores the count of all possible arrays from the ith position till the end, with prev as the value in (i-t)th index.
Follow the steps below to solve the problem:
- Initialize a global multidimensional array dp[][] to store the result of each recursive call.
- Find the multiples and divisors of all numbers from 1 to K and store them.
- Define a recursive function and perform the following operations:
- If the value of i is N, return 1 as a valid array has been formed.
- If the result of the state dp[i][prev] is already computed, return that calculated value.
- Iterate through all the multiples and divisors of ‘prev‘, and for each number call the recursive function for (i + 1)th index.
- The value at dp[0][1] will be the required answer.
Below is the implementation of the above approach :
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Declaring a DP array int dp[1005][1005];
// Vector of Vector for // storing all the factors and // multiples of a number vector<vector< int > > info(1005);
// Function to find the count // of arrays such that each // element is a multiple or // divisor of its neighbours. int countOfArrays( int index, int prev, int N)
{ // If i = N, return 1 as
// a valid array has been constructed.
if (index == N) {
return 1;
}
// If the state is already computed
if (dp[index][prev] != -1) {
return dp[index][prev];
}
dp[index][prev] = 0;
// Iterate through all the factors and
// multiples of the previous number
for ( auto num : info[prev]) {
// Call the function
// for index 'i + 1'.
dp[index][prev]
+= countOfArrays(index + 1,
num, N);
// Taking the remainder modulo 1e9+7.
dp[index][prev] %= 1000000007;
}
// Return the answer.
return dp[index][prev];
} // Utility function to find // the count of arrays such that // each element is a multiple // or divisor of its neighbours. int UtilCountOfArrays( int N, int K)
{ // Initialize the DP array with -1.
memset (dp, -1, sizeof dp);
// Finding the divisors and multiples
// till 'K', for all numbers from 1 to K
for ( int i = 1; i <= K; ++i) {
for ( int j = 1; j <= K; ++j) {
if (i % j == 0 or j % i == 0) {
info[i].push_back(j);
}
}
}
// Function call.
return countOfArrays(0, 1, N);
} // Driver code. int main()
{ // Input variables.
int N = 2;
int K = 3;
cout << UtilCountOfArrays(N, K) << endl;
return 0;
} |
import java.util.*;
class GFG {
// Declaring a DP array
static int [][] dp = new int [ 1005 ][ 1005 ];
// Vector of Vector for
// storing all the factors and
// multiples of a number
static ArrayList<ArrayList<Integer> > info
= new ArrayList<ArrayList<Integer> >();
// Function to find the count
// of arrays such that each
// element is a multiple or
// divisor of its neighbours.
public static int countOfArrays( int index, int prev,
int N)
{
// If i = N, return 1 as
// a valid array has been constructed.
if (index == N) {
return 1 ;
}
// If the state is already computed
if (dp[index][prev] != - 1 ) {
return dp[index][prev];
}
dp[index][prev] = 0 ;
// Iterate through all the factors and
// multiples of the previous number
for ( int num = 0 ; num < info.get(prev).size();
num++) {
// Call the function
// for index 'i + 1'.
dp[index][prev] += countOfArrays(
index + 1 , info.get(prev).get(num), N);
// Taking the remainder modulo 1e9+7.
dp[index][prev] %= 1000000007 ;
}
// Return the answer.
return dp[index][prev];
}
// Utility function to find
// the count of arrays such that
// each element is a multiple
// or divisor of its neighbours.
public static int UtilCountOfArrays( int N, int K)
{
// Initialize the DP array with -1.
for ( int i = 0 ; i < 1005 ; i++) {
for ( int j = 0 ; j < 1005 ; j++) {
dp[i][j] = - 1 ;
}
}
// Declaring info size
for ( int i = 0 ; i < 1005 ; i++) {
ArrayList<Integer> temp
= new ArrayList<Integer>();
info.add(temp);
}
// Finding the divisors and multiples
// till 'K', for all numbers from 1 to K
for ( int i = 1 ; i <= K; ++i) {
for ( int j = 1 ; j <= K; ++j) {
if ((i % j == 0 ) || (j % i == 0 )) {
info.get(i).add(j);
}
}
}
// Function call.
return countOfArrays( 0 , 1 , N);
}
public static void main(String[] args)
{
// Input variables.
int N = 2 ;
int K = 3 ;
System.out.println(UtilCountOfArrays(N, K));
}
} // This code is contributed by ninja_hattori. |
# pyprogram for the above approach # Declaring a DP array dp = [[ - 1 for _ in range ( 1005 )] for _ in range ( 1005 )]
# Vector of Vector for # storing all the factors and # multiples of a number info = [[] for _ in range ( 1005 )]
# Function to find the count # of arrays such that each # element is a multiple or # divisor of its neighbours. def countOfArrays(index, prev, N):
# If i = N, return 1 as
# a valid array has been constructed.
if (index = = N):
return 1
# If the state is already computed
if (dp[index][prev] ! = - 1 ):
return dp[index][prev]
dp[index][prev] = 0
# Iterate through all the factors and
# multiples of the previous number
for num in info[prev]:
# Call the function
# for index 'i + 1'.
dp[index][prev] + = countOfArrays(index + 1 , num, N)
# Taking the remainder modulo 1e9+7.
dp[index][prev] % = 1000000007
# Return the answer.
return dp[index][prev]
# Utility function to find # the count of arrays such that # each element is a multiple # or divisor of its neighbours. def UtilCountOfArrays(N, K):
# Initialize the DP array with -1.
# Finding the divisors and multiples
# till 'K', for all numbers from 1 to K
for i in range ( 1 , K + 1 ):
for j in range ( 1 , K + 1 ):
if (i % j = = 0 or j % i = = 0 ):
info[i].append(j)
# Function call.
return countOfArrays( 0 , 1 , N)
# Driver code. if __name__ = = "__main__" :
# Input variables.
N = 2
K = 3
print (UtilCountOfArrays(N, K))
# This code is contributed by rakeshsahni
|
<script> // JavaScript code for the above approach
// Declaring a DP array
let dp = new Array(1005);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(1005).fill(-1);
}
// Vector of Vector for
// storing all the factors and
// multiples of a number
let info = new Array(1005);
for (let i = 0; i < info.length; i++) {
info[i] = [];
}
// Function to find the count
// of arrays such that each
// element is a multiple or
// divisor of its neighbours.
function countOfArrays(index, prev, N) {
// If i = N, return 1 as
// a valid array has been constructed.
if (index == N) {
return 1;
}
// If the state is already computed
if (dp[index][prev] != -1) {
return dp[index][prev];
}
dp[index][prev] = 0;
// Iterate through all the factors and
// multiples of the previous number
for (let num of info[prev]) {
// Call the function
// for index 'i + 1'.
dp[index][prev]
+= countOfArrays(index + 1,
num, N);
// Taking the remainder modulo 1e9+7.
dp[index][prev] %= 1000000007;
}
// Return the answer.
return dp[index][prev];
}
// Utility function to find
// the count of arrays such that
// each element is a multiple
// or divisor of its neighbours.
function UtilCountOfArrays(N, K) {
// Initialize the DP array with -1.
// Finding the divisors and multiples
// till 'K', for all numbers from 1 to K
for (let i = 1; i <= K; ++i) {
for (let j = 1; j <= K; ++j) {
if (i % j == 0 || j % i == 0) {
info[i].push(j);
}
}
}
// Function call.
return countOfArrays(0, 1, N);
}
// Driver code.
// Input variables.
let N = 2;
let K = 3;
document.write(UtilCountOfArrays(N, K) + '<br>' );
// This code is contributed by Potta Lokesh
</script>
|
// C# program to implement above approach using System;
using System.Collections.Generic;
class GFG
{ // Declaring a DP array
static int [,] dp = new int [1005, 1005];
// Vector of Vector for
// storing all the factors and
// multiples of a number
static List<List< int > > info
= new List<List< int > >();
// Function to find the count
// of arrays such that each
// element is a multiple or
// divisor of its neighbours.
public static int countOfArrays( int index, int prev,
int N)
{
// If i = N, return 1 as
// a valid array has been constructed.
if (index == N) {
return 1;
}
// If the state is already computed
if (dp[index, prev] != -1) {
return dp[index, prev];
}
dp[index, prev] = 0;
// Iterate through all the factors and
// multiples of the previous number
for ( int num = 0; num < info[prev].Count;
num++) {
// Call the function
// for index 'i + 1'.
dp[index, prev] += countOfArrays(
index + 1, info[prev].Count, N);
// Taking the remainder modulo 1e9+7.
dp[index, prev] %= 1000000007;
}
// Return the answer.
return dp[index, prev];
}
// Utility function to find
// the count of arrays such that
// each element is a multiple
// or divisor of its neighbours.
public static int UtilCountOfArrays( int N, int K)
{
// Initialize the DP array with -1.
for ( int i = 0; i < 1005; i++) {
for ( int j = 0; j < 1005; j++) {
dp[i, j] = -1;
}
}
// Declaring info size
for ( int i = 0; i < 1005; i++) {
List< int > temp
= new List< int >();
info.Add(temp);
}
// Finding the divisors and multiples
// till 'K', for all numbers from 1 to K
for ( int i = 1; i <= K; ++i) {
for ( int j = 1; j <= K; ++j) {
if ((i % j == 0) || (j % i == 0)) {
info[i].Add(j);
}
}
}
// Function call.
return countOfArrays(0, 1, N) + 1;
}
// Driver Code
public static void Main()
{
// Input variables.
int N = 2;
int K = 3;
Console.Write(UtilCountOfArrays(N, K));
}
} // This code is contributed by sanjoy_62. |
7
Time Complexity: O(N * K * √K)
Auxiliary Space: O(N * K)
Iterative approach : Using DP Tabulation method
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 2D DP array dp of size (N+1) x (K+1).
- For each i in the range [2,N], and each j in the range [1,K], calculate dp[i][j] as follows:
a. Set dp[i][j] to 0.
b. For each k in the range [1,K], if j is divisible by k or k is divisible by j, then add dp[i-1][k] to dp[i][j].
c. Take the result of the sum and calculate it modulo 1000000007. - Calculate the answer ans as the sum of dp[N][j] for each j in the range [1,K].
- Take the result of the sum and calculate it modulo 1000000007.
- finally return the answer ans.
Implementation :
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Utility function to find // the count of arrays such that // each element is a multiple int UtilCountOfArrays( int N, int K)
{ // Create a 2D DP array
int dp[N+1][K+1];
// Initialize dp[1][j] to 1 for each j
for ( int j=1; j<=K; j++) {
dp[1][j] = 1;
}
// Calculate dp[i][j] for each i and j
for ( int i=2; i<=N; i++) {
for ( int j=1; j<=K; j++) {
dp[i][j] = 0;
for ( int k=1; k<=K; k++) {
if (j%k==0 || k%j==0) {
dp[i][j] += dp[i-1][k];
dp[i][j] %= 1000000007;
}
}
}
}
// Calculate the answer
int ans = 0;
for ( int j=1; j<=K; j++) {
ans += dp[N][j];
ans %= 1000000007;
}
// Return the answer
return ans;
} // Driver code. int main()
{ // Input variables.
int N = 2;
int K = 3;
cout << UtilCountOfArrays(N, K) << endl;
return 0;
} // this code is contributed by bhardwajji |
// Java program for the above approach import java.util.*;
class Main {
// Utility function to find
// the count of arrays such that
// each element is a multiple
static int UtilCountOfArrays( int N, int K)
{
// Create a 2D DP array
int [][] dp = new int [N + 1 ][K + 1 ];
// Initialize dp[1][j] to 1 for each j
for ( int j = 1 ; j <= K; j++) {
dp[ 1 ][j] = 1 ;
}
// Calculate dp[i][j] for each i and j
for ( int i = 2 ; i <= N; i++) {
for ( int j = 1 ; j <= K; j++) {
dp[i][j] = 0 ;
for ( int k = 1 ; k <= K; k++) {
if (j % k == 0 || k % j == 0 ) {
dp[i][j] += dp[i - 1 ][k];
dp[i][j] %= 1000000007 ;
}
}
}
}
// Calculate the answer
int ans = 0 ;
for ( int j = 1 ; j <= K; j++) {
ans += dp[N][j];
ans %= 1000000007 ;
}
// Return the answer
return ans;
}
// Driver code.
public static void main(String[] args)
{
// Input variables.
int N = 2 ;
int K = 3 ;
System.out.println(UtilCountOfArrays(N, K));
}
} |
# Python 3 program for the above approach # Utility function to find # the count of arrays such that # each element is a multiple def UtilCountOfArrays(N, K):
# Create a 2D DP array
dp = [[ 0 for j in range (K + 1 )] for i in range (N + 1 )]
# Initialize dp[1][j] to 1 for each j
for j in range ( 1 , K + 1 ):
dp[ 1 ][j] = 1
# Calculate dp[i][j] for each i and j
for i in range ( 2 , N + 1 ):
for j in range ( 1 , K + 1 ):
for k in range ( 1 , K + 1 ):
if (j % k = = 0 or k % j = = 0 ):
dp[i][j] + = dp[i - 1 ][k]
dp[i][j] % = 1000000007
# Calculate the answer
ans = 0
for j in range ( 1 , K + 1 ):
ans + = dp[N][j]
ans % = 1000000007
# Return the answer
return ans
# Driver code if __name__ = = '__main__' :
# Input variables
N = 2
K = 3
print (UtilCountOfArrays(N, K))
|
// Utility function to find // the count of arrays such that // each element is a multiple function UtilCountOfArrays(N, K) {
// Create a 2D DP array
let dp = new Array(N + 1).fill(0).map(() => new Array(K + 1).fill(0));
// Initialize dp[1][j] to 1 for each j
for (let j = 1; j <= K; j++) {
dp[1][j] = 1;
}
// Calculate dp[i][j] for each i and j
for (let i = 2; i <= N; i++) {
for (let j = 1; j <= K; j++) {
for (let k = 1; k <= K; k++) {
if (j % k == 0 || k % j == 0) {
dp[i][j] += dp[i - 1][k];
dp[i][j] %= 1000000007;
}
}
}
}
// Calculate the answer
let ans = 0;
for (let j = 1; j <= K; j++) {
ans += dp[N][j];
ans %= 1000000007;
}
// Return the answer
return ans;
} // Driver code let N = 2; let K = 3; console.log(UtilCountOfArrays(N, K)); |
// C# program for the above approach using System;
class GFG {
// Utility function to find
// the count of arrays such that // each element is a multiple static int UtilCountOfArrays( int N, int K)
{ // Create a 2D DP array
int [,] dp = new int [N+1, K+1];
// Initialize dp[1][j] to 1 for each j
for ( int j=1; j<=K; j++) {
dp[1,j] = 1;
}
// Calculate dp[i][j] for each i and j
for ( int i=2; i<=N; i++) {
for ( int j=1; j<=K; j++) {
dp[i,j] = 0;
for ( int k=1; k<=K; k++) {
if (j%k==0 || k%j==0) {
dp[i,j] += dp[i-1,k];
dp[i,j] %= 1000000007;
}
}
}
}
// Calculate the answer
int ans = 0;
for ( int j=1; j<=K; j++) {
ans += dp[N,j];
ans %= 1000000007;
}
// Return the answer
return ans;
} // Driver code static void Main()
{ // Input variables.
int N = 2;
int K = 3;
Console.WriteLine(UtilCountOfArrays(N, K));
} } |
Output:
7
Time Complexity: O(N*K^2)
Auxiliary Space: O(N*K^2)