Count of N size Arrays with each element as multiple or divisor of its neighbours
Last Updated :
11 Apr, 2023
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++
#include <bits/stdc++.h>
using namespace std;
int dp[1005][1005];
vector<vector< int > > info(1005);
int countOfArrays( int index, int prev, int N)
{
if (index == N) {
return 1;
}
if (dp[index][prev] != -1) {
return dp[index][prev];
}
dp[index][prev] = 0;
for ( auto num : info[prev]) {
dp[index][prev]
+= countOfArrays(index + 1,
num, N);
dp[index][prev] %= 1000000007;
}
return dp[index][prev];
}
int UtilCountOfArrays( int N, int K)
{
memset (dp, -1, sizeof dp);
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);
}
}
}
return countOfArrays(0, 1, N);
}
int main()
{
int N = 2;
int K = 3;
cout << UtilCountOfArrays(N, K) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
static int [][] dp = new int [ 1005 ][ 1005 ];
static ArrayList<ArrayList<Integer> > info
= new ArrayList<ArrayList<Integer> >();
public static int countOfArrays( int index, int prev,
int N)
{
if (index == N) {
return 1 ;
}
if (dp[index][prev] != - 1 ) {
return dp[index][prev];
}
dp[index][prev] = 0 ;
for ( int num = 0 ; num < info.get(prev).size();
num++) {
dp[index][prev] += countOfArrays(
index + 1 , info.get(prev).get(num), N);
dp[index][prev] %= 1000000007 ;
}
return dp[index][prev];
}
public static int UtilCountOfArrays( int N, int K)
{
for ( int i = 0 ; i < 1005 ; i++) {
for ( int j = 0 ; j < 1005 ; j++) {
dp[i][j] = - 1 ;
}
}
for ( int i = 0 ; i < 1005 ; i++) {
ArrayList<Integer> temp
= new ArrayList<Integer>();
info.add(temp);
}
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);
}
}
}
return countOfArrays( 0 , 1 , N);
}
public static void main(String[] args)
{
int N = 2 ;
int K = 3 ;
System.out.println(UtilCountOfArrays(N, K));
}
}
|
Python3
dp = [[ - 1 for _ in range ( 1005 )] for _ in range ( 1005 )]
info = [[] for _ in range ( 1005 )]
def countOfArrays(index, prev, N):
if (index = = N):
return 1
if (dp[index][prev] ! = - 1 ):
return dp[index][prev]
dp[index][prev] = 0
for num in info[prev]:
dp[index][prev] + = countOfArrays(index + 1 , num, N)
dp[index][prev] % = 1000000007
return dp[index][prev]
def UtilCountOfArrays(N, 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)
return countOfArrays( 0 , 1 , N)
if __name__ = = "__main__" :
N = 2
K = 3
print (UtilCountOfArrays(N, K))
|
Javascript
<script>
let dp = new Array(1005);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(1005).fill(-1);
}
let info = new Array(1005);
for (let i = 0; i < info.length; i++) {
info[i] = [];
}
function countOfArrays(index, prev, N) {
if (index == N) {
return 1;
}
if (dp[index][prev] != -1) {
return dp[index][prev];
}
dp[index][prev] = 0;
for (let num of info[prev]) {
dp[index][prev]
+= countOfArrays(index + 1,
num, N);
dp[index][prev] %= 1000000007;
}
return dp[index][prev];
}
function UtilCountOfArrays(N, 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);
}
}
}
return countOfArrays(0, 1, N);
}
let N = 2;
let K = 3;
document.write(UtilCountOfArrays(N, K) + '<br>' );
</script>
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int [,] dp = new int [1005, 1005];
static List<List< int > > info
= new List<List< int > >();
public static int countOfArrays( int index, int prev,
int N)
{
if (index == N) {
return 1;
}
if (dp[index, prev] != -1) {
return dp[index, prev];
}
dp[index, prev] = 0;
for ( int num = 0; num < info[prev].Count;
num++) {
dp[index, prev] += countOfArrays(
index + 1, info[prev].Count, N);
dp[index, prev] %= 1000000007;
}
return dp[index, prev];
}
public static int UtilCountOfArrays( int N, int K)
{
for ( int i = 0; i < 1005; i++) {
for ( int j = 0; j < 1005; j++) {
dp[i, j] = -1;
}
}
for ( int i = 0; i < 1005; i++) {
List< int > temp
= new List< int >();
info.Add(temp);
}
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);
}
}
}
return countOfArrays(0, 1, N) + 1;
}
public static void Main()
{
int N = 2;
int K = 3;
Console.Write(UtilCountOfArrays(N, K));
}
}
|
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++
#include <bits/stdc++.h>
using namespace std;
int UtilCountOfArrays( int N, int K)
{
int dp[N+1][K+1];
for ( int j=1; j<=K; j++) {
dp[1][j] = 1;
}
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;
}
}
}
}
int ans = 0;
for ( int j=1; j<=K; j++) {
ans += dp[N][j];
ans %= 1000000007;
}
return ans;
}
int main()
{
int N = 2;
int K = 3;
cout << UtilCountOfArrays(N, K) << endl;
return 0;
}
|
Java
import java.util.*;
class Main {
static int UtilCountOfArrays( int N, int K)
{
int [][] dp = new int [N + 1 ][K + 1 ];
for ( int j = 1 ; j <= K; j++) {
dp[ 1 ][j] = 1 ;
}
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 ;
}
}
}
}
int ans = 0 ;
for ( int j = 1 ; j <= K; j++) {
ans += dp[N][j];
ans %= 1000000007 ;
}
return ans;
}
public static void main(String[] args)
{
int N = 2 ;
int K = 3 ;
System.out.println(UtilCountOfArrays(N, K));
}
}
|
Python3
def UtilCountOfArrays(N, K):
dp = [[ 0 for j in range (K + 1 )] for i in range (N + 1 )]
for j in range ( 1 , K + 1 ):
dp[ 1 ][j] = 1
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
ans = 0
for j in range ( 1 , K + 1 ):
ans + = dp[N][j]
ans % = 1000000007
return ans
if __name__ = = '__main__' :
N = 2
K = 3
print (UtilCountOfArrays(N, K))
|
Javascript
function UtilCountOfArrays(N, K) {
let dp = new Array(N + 1).fill(0).map(() => new Array(K + 1).fill(0));
for (let j = 1; j <= K; j++) {
dp[1][j] = 1;
}
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;
}
}
}
}
let ans = 0;
for (let j = 1; j <= K; j++) {
ans += dp[N][j];
ans %= 1000000007;
}
return ans;
}
let N = 2;
let K = 3;
console.log(UtilCountOfArrays(N, K));
|
C#
using System;
class GFG {
static int UtilCountOfArrays( int N, int K)
{
int [,] dp = new int [N+1, K+1];
for ( int j=1; j<=K; j++) {
dp[1,j] = 1;
}
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;
}
}
}
}
int ans = 0;
for ( int j=1; j<=K; j++) {
ans += dp[N,j];
ans %= 1000000007;
}
return ans;
}
static void Main()
{
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)
Share your thoughts in the comments
Please Login to comment...