Open In App

Count of N size Arrays with each element as multiple or divisor of its neighbours

Last Updated : 11 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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++




// 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;
}


Java




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.


Python3




# 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


Javascript




<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#




// 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.


Output

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++




// 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




// 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));
    }
}


Python3




# 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))


Javascript




// 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#




// 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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads