Count of arrays in which all adjacent elements are such that one of them divide the another
Given two positive integer n and n. The task is to find the number of arrays of size n that can be formed such that :
- Each element is in range [1, m]
- All adjacent element are such that one of them divide the another i.e element Ai divides Ai + 1 or Ai + 1 divides Ai + 2.
Examples:
Input : n = 3, m = 3.
Output : 17
{1,1,1}, {1,1,2}, {1,1,3}, {1,2,1},
{1,2,2}, {1,3,1}, {1,3,3}, {2,1,1},
{2,1,2}, {2,1,3}, {2,2,1}, {2,2,2},
{3,1,1}, {3,1,2}, {3,1,3}, {3,3,1},
{3,3,3} are possible arrays.
Input : n = 1, m = 10.
Output : 10
We try to find number of possible values at each index of the array. First, at index 0 all values are possible from 1 to m. Now observe for each index, we can reach either to its multiple or its factor. So, precompute that and store it for all the elements. Hence for each position i, ending with integer x, we can go to next position i + 1, with the array ending in integer with multiple of x or factor of x. Also, multiple of x or factor of x must be less than m.
So, we define an 2D array dp[i][j], which is number of possible array (divisible adjacent element) of size i with j as its first index element.
1 <= i <= m, dp[1][m] = 1.
for 1 <= j <= m and 2 <= i <= n
dp[i][j] = dp[i-1][j] + number of factor
of previous element less than m
+ number of multiples of previous
element less than m.
Below is the implementation of this approach:
C++
#include <bits/stdc++.h>
#define MAX 1000
using namespace std;
int numofArray( int n, int m)
{
int dp[MAX][MAX];
vector< int > di[MAX];
vector< int > mu[MAX];
memset (dp, 0, sizeof dp);
memset (di, 0, sizeof di);
memset (mu, 0, sizeof mu);
for ( int i = 1; i <= m; i++)
{
for ( int j = 2*i; j <= m; j += i)
{
di[j].push_back(i);
mu[i].push_back(j);
}
di[i].push_back(i);
}
for ( int i = 1; i <= m; i++)
dp[1][i] = 1;
for ( int i = 2; i <= n; i++)
{
for ( int j = 1; j <= m; j++)
{
dp[i][j] = 0;
for ( auto x:di[j])
dp[i][j] += dp[i-1][x];
for ( auto x:mu[j])
dp[i][j] += dp[i-1][x];
}
}
int ans = 0;
for ( int i = 1; i <= m; i++)
{
ans += dp[n][i];
di[i].clear();
mu[i].clear();
}
return ans;
}
int main()
{
int n = 3, m = 3;
cout << numofArray(n, m) << "\n" ;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int MAX = 1000 ;
static int numofArray( int n, int m)
{
int [][]dp = new int [MAX][MAX];
Vector<Integer> []di = new Vector[MAX];
Vector<Integer> []mu = new Vector[MAX];
for ( int i = 0 ; i < MAX; i++)
{
for ( int j = 0 ; j < MAX; j++)
{
dp[i][j] = 0 ;
}
}
for ( int i = 0 ; i < MAX; i++)
{
di[i] = new Vector<>();
mu[i] = new Vector<>();
}
for ( int i = 1 ; i <= m; i++)
{
for ( int j = 2 * i; j <= m; j += i)
{
di[j].add(i);
mu[i].add(j);
}
di[i].add(i);
}
for ( int i = 1 ; i <= m; i++)
dp[ 1 ][i] = 1 ;
for ( int i = 2 ; i <= n; i++)
{
for ( int j = 1 ; j <= m; j++)
{
dp[i][j] = 0 ;
for (Integer x:di[j])
dp[i][j] += dp[i - 1 ][x];
for (Integer x:mu[j])
dp[i][j] += dp[i - 1 ][x];
}
}
int ans = 0 ;
for ( int i = 1 ; i <= m; i++)
{
ans += dp[n][i];
di[i].clear();
mu[i].clear();
}
return ans;
}
public static void main(String[] args)
{
int n = 3 , m = 3 ;
System.out.println(numofArray(n, m));
}
}
|
Python3
MAX = 1000
def numofArray(n, m):
dp = [[ 0 for i in range ( MAX )] for j in range ( MAX )]
di = [[] for i in range ( MAX )]
mu = [[] for i in range ( MAX )]
for i in range ( 1 , m + 1 ):
for j in range ( 2 * i, m + 1 , i):
di[j].append(i)
mu[i].append(j)
di[i].append(i)
for i in range ( 1 , m + 1 ):
dp[ 1 ][i] = 1
for i in range ( 2 , n + 1 ):
for j in range ( 1 , m + 1 ):
dp[i][j] = 0
for x in di[j]:
dp[i][j] + = dp[i - 1 ][x]
for x in mu[j]:
dp[i][j] + = dp[i - 1 ][x]
ans = 0
for i in range ( 1 , m + 1 ):
ans + = dp[n][i]
di[i].clear()
mu[i].clear()
return ans
if __name__ = = "__main__" :
n = m = 3
print (numofArray(n, m))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int MAX = 1000;
static int numofArray( int n, int m)
{
int [,]dp = new int [MAX, MAX];
List< int > []di = new List< int >[MAX];
List< int > []mu = new List< int >[MAX];
for ( int i = 0; i < MAX; i++)
{
for ( int j = 0; j < MAX; j++)
{
dp[i, j] = 0;
}
}
for ( int i = 0; i < MAX; i++)
{
di[i] = new List< int >();
mu[i] = new List< int >();
}
for ( int i = 1; i <= m; i++)
{
for ( int j = 2 * i; j <= m; j += i)
{
di[j].Add(i);
mu[i].Add(j);
}
di[i].Add(i);
}
for ( int i = 1; i <= m; i++)
dp[1, i] = 1;
for ( int i = 2; i <= n; i++)
{
for ( int j = 1; j <= m; j++)
{
dp[i, j] = 0;
foreach ( int x in di[j])
dp[i, j] += dp[i - 1, x];
foreach ( int x in mu[j])
dp[i, j] += dp[i - 1, x];
}
}
int ans = 0;
for ( int i = 1; i <= m; i++)
{
ans += dp[n, i];
di[i].Clear();
mu[i].Clear();
}
return ans;
}
public static void Main(String[] args)
{
int n = 3, m = 3;
Console.WriteLine(numofArray(n, m));
}
}
|
Javascript
<script>
let MAX = 1000;
function numofArray(n, m)
{
let dp = new Array(MAX);
let di = new Array(MAX);
let mu = new Array(MAX);
for (let i = 0; i < MAX; i++)
{
dp[i] = new Array(MAX);
for (let j = 0; j < MAX; j++)
{
dp[i][j] = 0;
}
}
for (let i = 0; i < MAX; i++)
{
di[i] = [];
mu[i] = [];
}
for (let i = 1; i <= m; i++)
{
for (let j = 2 * i; j <= m; j += i)
{
di[j].push(i);
mu[i].push(j);
}
di[i].push(i);
}
for (let i = 1; i <= m; i++)
dp[1][i] = 1;
for (let i = 2; i <= n; i++)
{
for (let j = 1; j <= m; j++)
{
dp[i][j] = 0;
for (let x = 0; x < di[j].length; x++)
dp[i][j] += dp[i - 1][di[j][x]];
for (let x = 0; x < mu[j].length; x++)
dp[i][j] += dp[i - 1][mu[j][x]];
}
}
let ans = 0;
for (let i = 1; i <= m; i++)
{
ans += dp[n][i];
di[i] = [];
mu[i] = [];
}
return ans;
}
let n = 3, m = 3;
document.write(numofArray(n, m));
</script>
|
Time Complexity: O(N*M).
Last Updated :
11 Jul, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...