# Minimal product subsequence where adjacent elements are separated by a maximum distance of K

Given an array **arr[]** and an integer **K**, the task is to find out the minimum product of a subsequence where adjacent elements of the subsequence are separated by a maximum distance of K.**Note:** The subsequence should include the first and the last element of the array.

**Examples:**

Input:arr[] = { 1, 2, 3, 4 }, K = 2Output:8

The first element in the subsequence is 1. From 1, we can move to either 2 or 3 (since K = 2). We can move to 3 and then to 4 to have a product of 12. However,we can also move to 2 and then to 4to have a product of 8. Minimal product subsequence = { 1, 2, 4 }Input:arr[] = { 2, 3 }, K = 2Output:6

**Naive Approach:** A naive approach is to generate all subsequences of the array and maintain a difference of indices between the adjacent elements and find the minimal product subsequence. **Efficient Approach:** An efficient approach is to use **dynamic programming**. Let **dp[i]** denote the minimum product of elements **till index ‘i’ including arr[i]** who are separated by a maximum distance of **K**. Then dp[i] can be formulated as follows:

dp[i] = arr[i] * min{dp[j]} where j < i and 1 <= i - j <= K.

To calculate **dp[i]**, a window of size **K** can be maintained and traversed to find the minimum of **dp[j]** which can then be **multiplied to arr[i]**. However, this will result in an **O(N*K)** solution.

To optimize the solution further, values of the product can be stored in an STL set and the minimum value of the product can then be found out in **O(log n)** time. Since storing products can be a cumbersome task since the product can easily exceed 10^{18}, therefore we will store log values of products since log is a monotonic function and minimization of log values will automatically imply minimization of products.

Below is the implementation of the above approach:

## CPP

`// C++ implementation of the above approach.` `#include <bits/stdc++.h>` `#define mp make_pair` `#define ll long long` `using` `namespace` `std;` `const` `int` `mod = 1000000007;` `const` `int` `MAX = 100005;` `// Function to get the minimum product of subsequence such that` `// adjacent elements are separated by a max distance of K` `int` `minimumProductSubsequence(` `int` `* arr, ` `int` `n, ` `int` `k)` `{` ` ` `multiset<pair<` `double` `, ` `int` `> > s;` ` ` `ll dp[MAX];` ` ` `double` `p[MAX];` ` ` `dp[0] = arr[0];` ` ` `p[0] = ` `log` `(arr[0]);` ` ` `// multiset will hold pairs` ` ` `// pair = (log value of product, dp[j] value)` ` ` `// dp[j] = minimum product % mod` ` ` `// multiset will be sorted according to log values` ` ` `// Therefore, corresponding to the minimum log value` ` ` `// dp[j] value can be obtained.` ` ` `s.insert(mp(p[0], dp[0]));` ` ` `// For the first k-sized window.` ` ` `for` `(` `int` `i = 1; i < k; i++) {` ` ` `double` `l = (s.begin())->first;` ` ` `ll min = (s.begin())->second;` ` ` `// Update log value by adding previous` ` ` `// minimum log value` ` ` `p[i] = ` `log` `(arr[i]) + l;` ` ` `// Update dp[i]` ` ` `dp[i] = (arr[i] * min) % mod;` ` ` `// Insert it again into the multiset` ` ` `// since it is within the k-size window` ` ` `s.insert(mp(p[i], dp[i]));` ` ` `}` ` ` `for` `(` `int` `i = k; i < n; i++) {` ` ` `double` `l = (s.begin())->first;` ` ` `ll min = (s.begin())->second;` ` ` `p[i] = ` `log` `(arr[i]) + l;` ` ` `dp[i] = (arr[i] * min) % mod;` ` ` `// Eliminate previous value which falls out` ` ` `// of the k-sized window` ` ` `multiset<pair<` `double` `, ` `int` `> >::iterator it;` ` ` `it = s.find(mp(p[i - k], dp[i - k]));` ` ` `s.erase(it);` ` ` `// Insert newest value to enter in` ` ` `// the k-sized window.` ` ` `s.insert(mp(p[i], dp[i]));` ` ` `}` ` ` `// dp[n - 1] will have minimum product %` ` ` `// mod such that adjacent elements are` ` ` `// separated by a max distance K` ` ` `return` `dp[n - 1];` `}` `// Driver Code` `int` `main()` `{` ` ` `int` `arr[] = { 1, 2, 3, 4 };` ` ` `int` `n = ` `sizeof` `(arr) / ` `sizeof` `(arr[0]);` ` ` `int` `k = 2;` ` ` `cout << minimumProductSubsequence(arr, n, k);` ` ` `return` `0;` `}` |

## Python3

`# Python3 implementation of the above approach.` `import` `math` ` ` `mod ` `=` `1000000007` `;` `MAX` `=` `100005` `;` ` ` `# Function to get the minimum product of subsequence such that` `# adjacent elements are separated by a max distance of K` `def` `minimumProductSubsequence(arr, n, k):` ` ` `s ` `=` `[]` ` ` ` ` `dp ` `=` `[` `0` `for` `i ` `in` `range` `(` `MAX` `)];` ` ` `p ` `=` `[` `0.0` `for` `i ` `in` `range` `(` `MAX` `)];` ` ` ` ` `dp[` `0` `] ` `=` `arr[` `0` `];` ` ` `p[` `0` `] ` `=` `math.log(arr[` `0` `]);` ` ` ` ` `# multiset will hold pairs` ` ` `# pair = (log value of product, dp[j] value)` ` ` `# dp[j] = minimum product % mod` ` ` `# multiset will be sorted according to log values` ` ` `# Therefore, corresponding to the minimum log value` ` ` `# dp[j] value can be obtained.` ` ` `s.append([p[` `0` `], dp[` `0` `]]);` ` ` `s.sort()` ` ` ` ` `# For the first k-sized window.` ` ` `for` `i ` `in` `range` `(` `1` `, k):` ` ` ` ` `l ` `=` `s[` `0` `][` `0` `]` ` ` `min` `=` `s[` `0` `][` `1` `]` ` ` ` ` `# Update log value by adding previous` ` ` `# minimum log value` ` ` `p[i] ` `=` `math.log(arr[i]) ` `+` `l;` ` ` ` ` `# Update dp[i]` ` ` `dp[i] ` `=` `(arr[i] ` `*` `min` `) ` `%` `mod;` ` ` ` ` `# Insert it again into the multiset` ` ` `# since it is within the k-size window` ` ` `s.append([p[i], dp[i]]);` ` ` `s.sort()` ` ` ` ` `for` `i ` `in` `range` `(k, n):` ` ` ` ` `l ` `=` `s[` `0` `][` `0` `]` ` ` `min` `=` `s[` `0` `][` `1` `]` ` ` `p[i] ` `=` `math.log(arr[i]) ` `+` `l;` ` ` `dp[i] ` `=` `(arr[i] ` `*` `min` `) ` `%` `mod;` ` ` ` ` `# Eliminate previous value which falls out` ` ` `# of the k-sized window` ` ` `if` `[p[i ` `-` `k], dp[i ` `-` `k]] ` `in` `s:` ` ` `s.pop(s.index([p[i ` `-` `k], dp[i ` `-` `k]]))` ` ` ` ` `# Insert newest value to enter in` ` ` `# the k-sized window.` ` ` `s.append([p[i], dp[i]]);` ` ` `s.sort()` ` ` ` ` `# dp[n - 1] will have minimum product %` ` ` `# mod such that adjacent elements are` ` ` `# separated by a max distance K` ` ` `return` `dp[n ` `-` `1` `];` `# Driver Code` `if` `__name__` `=` `=` `'__main__'` `:` ` ` ` ` `arr ` `=` `[ ` `1` `, ` `2` `, ` `3` `, ` `4` `]` ` ` `n ` `=` `len` `(arr)` ` ` ` ` `k ` `=` `2` `;` ` ` ` ` `print` `(minimumProductSubsequence(arr, n, k))` ` ` `# This code is contributed by rutvik_56` |

**Output**

8

**Time Complexity: **O(N* log(N))**Auxiliary Space: **O(N)