Minimum sum of multiplications of n numbers
Last Updated :
04 May, 2025
Given an integer array arr[]
of length n
. Your goal is to reduce the array to a single element by repeatedly applying the following operation
- Select any two adjacent elements, call them
x
and y
. - Remove
x
and y
from the array. - Insert a new element equal to
(x + y) mod 100
at their position. - The cost of this operation is
x * y
.
You must perform exactly n‑1
operations (so that one element remains), and your task is to minimize the total cost, i.e., the sum of all individual x * y
costs.
Examples:
Input: arr[] = [40, 60, 20]
Output: 2400
Explanation: There are two possible cases:
Sequence 1:
1. Combine 40 & 60 → cost 2400, new element 0 → [0, 20]
2. Combine 0 & 20 → cost 0, new element 20 → [20], and total becomes 2400.
Sequence 2:
1. Combine 60 & 20 → cost 1200, new element 80 → [40, 80]
2. Combine 40 & 80 → cost 3200, new element 20 → [20], and total becomes 4400.
Input: arr[] = [5, 6]
Output: 30
Explanation: There is only one possible operation, 5 * 6 = 30.
[Expected Approach - 1] - Using Memoization and Prefix Sum - O(n ^ 3) Time and O(n ^ 2) Space
The idea is to partition the array in every possible way, similar to Matrix chain Multiplication Dynamic Programming, and find the minimum possible cost. To do so, firstly create the 2d array memo[][] where each element memo[i][j], stores the minimum cost required to perform the given operation for the subarray arr[i..j]. Now start for the whole array, and recursively calculate the cost of smaller subparts, and add the multiplication and store the minimum of them. For the subarray arr[i...j], the value memo[i][j] will be calculated as:
memo[i][j] = min(memo[i][k] + memo[k + 1][j] + modSum(i, k) * modSum(k + 1, j)), for i <= k < j.
Follow the below given steps:
- Build a prefix‑sum array (
prefix
) so that you can get the sum of any subarray in O(1) time via a simple subtraction and modulo operation. - Create an
n×n
table (memo
) initialized to –1 to indicate “not yet computed.” - Call
findMinCost(arr, 0, n‑1, prefix, memo)
and return its value. - In
findMinCost(arr, i, j, prefix, memo)
:- If
i == j
, return 0. - If
memo[i][j] != -1
, return the stored value. - Set
memo[i][j] = INT_MAX
. - For
k
from i
to j‑1
:- Compute
a = findMinCost(arr, i, k, prefix, memo)
. - Compute
b = findMinCost(arr, k+1, j, prefix, memo)
. - Compute
c = sum(i, k, prefix) * sum(k+1, j, prefix)
. - Update
memo[i][j] = min(memo[i][j], a + b + c)
.
- Return
memo[i][j]
.
Below is given the implementation:
C++
#include <bits/stdc++.h>
using namespace std;
// function to calculate the
// sum from a[i] to a[j]
int sum(int i, int j, vector<int> &prefix) {
if (i == 0)
return prefix[j] % 100;
return (prefix[j] - prefix[i - 1]) % 100;
}
int findMinCost(vector<int> &arr, int i, int j,
vector<int> &prefix, vector<vector<int>> &memo) {
// base case
if (i == j)
return 0;
// if already computed
if (memo[i][j] != -1)
return memo[i][j];
// store a max value
memo[i][j] = INT_MAX;
// partition the array at every index
for (int k = i; k < j; k++) {
// calculate the cost of the partition
int a = findMinCost(arr, i, k, prefix, memo);
int b = findMinCost(arr, k + 1, j, prefix, memo);
int c = sum(i, k, prefix) * sum(k + 1, j, prefix);
int cost = a + b + c;
// store the minimum cost
memo[i][j] = min(memo[i][j], cost);
}
// return the minimum
return memo[i][j];
}
int minCost(vector<int> &arr) {
int n = arr.size();
// initialize the memo
vector<vector<int>> memo(n, vector<int>(n, -1));
// to store prefix sum
vector<int> prefix(n);
prefix[0] = arr[0];
for(int i = 1; i < n; i++) {
prefix[i] = arr[i] + prefix[i - 1];
}
return findMinCost(arr, 0, n - 1, prefix, memo);
}
int main() {
vector<int> arr = {40, 60, 20};
cout << minCost(arr);
return 0;
}
Java
import java.util.*;
public class GfG {
public static int sum(int i, int j, List<Integer> prefix) {
// function to calculate the
// sum from a[i] to a[j]
if (i == 0)
return prefix.get(j) % 100;
return (prefix.get(j) - prefix.get(i - 1)) % 100;
}
public static int findMinCost(List<Integer> arr, int i, int j,
List<Integer> prefix, int[][] memo) {
// base case
if (i == j)
return 0;
// if already computed
if (memo[i][j] != -1)
return memo[i][j];
// store a max value
memo[i][j] = Integer.MAX_VALUE;
// partition the array at every index
for (int k = i; k < j; k++) {
// calculate the cost of the partition
int a = findMinCost(arr, i, k, prefix, memo);
int b = findMinCost(arr, k + 1, j, prefix, memo);
int c = sum(i, k, prefix) * sum(k + 1, j, prefix);
int cost = a + b + c;
// store the minimum cost
memo[i][j] = Math.min(memo[i][j], cost);
}
// return the minimum
return memo[i][j];
}
public static int minCost(List<Integer> arr) {
int n = arr.size();
// initialize the memo
int[][] memo = new int[n][n];
for (int[] row : memo) Arrays.fill(row, -1);
// to store prefix sum
List<Integer> prefix = new ArrayList<>();
prefix.add(arr.get(0));
for (int i = 1; i < n; i++) {
prefix.add(arr.get(i) + prefix.get(i - 1));
}
return findMinCost(arr, 0, n - 1, prefix, memo);
}
public static void main(String[] args) {
List<Integer> arr = Arrays.asList(40, 60, 20);
System.out.print(minCost(arr));
}
}
Python
# function to calculate the
# sum from a[i] to a[j]
def sum(i, j, prefix):
if i == 0:
return prefix[j] % 100
return (prefix[j] - prefix[i - 1]) % 100
def findMinCost(arr, i, j,
prefix, memo):
# base case
if i == j:
return 0
# if already computed
if memo[i][j] != -1:
return memo[i][j]
# store a max value
memo[i][j] = float('inf')
# partition the array at every index
for k in range(i, j):
# calculate the cost of the partition
a = findMinCost(arr, i, k, prefix, memo)
b = findMinCost(arr, k + 1, j, prefix, memo)
c = sum(i, k, prefix) * sum(k + 1, j, prefix)
cost = a + b + c
# store the minimum cost
memo[i][j] = min(memo[i][j], cost)
# return the minimum
return memo[i][j]
def minCost(arr):
n = len(arr)
# initialize the memo
memo = [[-1] * n for _ in range(n)]
# to store prefix sum
prefix = [0] * n
prefix[0] = arr[0]
for i in range(1, n):
prefix[i] = arr[i] + prefix[i - 1]
return findMinCost(arr, 0, n - 1, prefix, memo)
if __name__ == "__main__":
arr = [40, 60, 20]
print(minCost(arr))
C#
using System;
using System.Collections.Generic;
public class GfG {
public static int sum(int i, int j, List<int> prefix) {
// function to calculate the
// sum from a[i] to a[j]
if (i == 0)
return prefix[j] % 100;
return (prefix[j] - prefix[i - 1]) % 100;
}
public static int findMinCost(List<int> arr, int i, int j,
List<int> prefix, int[,] memo) {
// base case
if (i == j)
return 0;
// if already computed
if (memo[i, j] != -1)
return memo[i, j];
// store a max value
memo[i, j] = int.MaxValue;
// partition the array at every index
for (int k = i; k < j; k++) {
// calculate the cost of the partition
int a = findMinCost(arr, i, k, prefix, memo);
int b = findMinCost(arr, k + 1, j, prefix, memo);
int c = sum(i, k, prefix) * sum(k + 1, j, prefix);
int cost = a + b + c;
// store the minimum cost
memo[i, j] = Math.Min(memo[i, j], cost);
}
// return the minimum
return memo[i, j];
}
public static int minCost(List<int> arr) {
int n = arr.Count;
// initialize the memo
int[,] memo = new int[n, n];
for (int x = 0; x < n; x++)
for (int y = 0; y < n; y++)
memo[x, y] = -1;
// to store prefix sum
List<int> prefix = new List<int>();
prefix.Add(arr[0]);
for (int i = 1; i < n; i++) {
prefix.Add(arr[i] + prefix[i - 1]);
}
return findMinCost(arr, 0, n - 1, prefix, memo);
}
public static void Main() {
List<int> arr = new List<int> {40, 60, 20};
Console.Write(minCost(arr));
}
}
JavaScript
// function to calculate the
// sum from a[i] to a[j]
function sum(i, j, prefix) {
if (i === 0)
return prefix[j] % 100;
return (prefix[j] - prefix[i - 1]) % 100;
}
function findMinCost(arr, i, j,
prefix, memo) {
// base case
if (i === j)
return 0;
// if already computed
if (memo[i][j] !== -1)
return memo[i][j];
// store a max value
memo[i][j] = Number.MAX_SAFE_INTEGER;
// partition the array at every index
for (let k = i; k < j; k++) {
// calculate the cost of the partition
let a = findMinCost(arr, i, k, prefix, memo);
let b = findMinCost(arr, k + 1, j, prefix, memo);
let c = sum(i, k, prefix) * sum(k + 1, j, prefix);
let cost = a + b + c;
// store the minimum cost
memo[i][j] = Math.min(memo[i][j], cost);
}
// return the minimum
return memo[i][j];
}
function minCost(arr) {
const n = arr.length;
// initialize the memo
const memo = Array.from({ length: n }, () => Array(n).fill(-1));
// to store prefix sum
const prefix = [];
prefix[0] = arr[0];
for (let i = 1; i < n; i++) {
prefix[i] = arr[i] + prefix[i - 1];
}
return findMinCost(arr, 0, n - 1, prefix, memo);
}
let arr = [40, 60, 20];
console.log(minCost(arr));
[Expected Approach - 2] - Using Tabulation and Prefix Sum - O(n ^ 2) Time and O(n ^ 2) Space
The idea is to build a bottom‑up DP table dp[i][j]
that holds the minimum cost to reduce the subarray arr[i…j]
to one element. We first compute prefix sums so that any subarray sum modulo 100 can be obtained in O(1). Then, we fill dp
by increasing subarray length: for each interval [i…j]
, we try every split point k
(from i
to j-1
), combine the two subintervals’ costs with the merge cost (sum(i,k) * sum(k+1,j))
, and take the minimum. At the end, dp[0][n-1]
is the answer.
Follow the below given steps:
- Compute a prefix array
prefix
of length n
:
prefix[0] = arr[0]
, and for i
= 1…n-1
,
prefix[i] = prefix[i-1] + arr[i]
. - Create an
n×n
DP table dp
, initialize all dp[i][i] = 0
. - For subarray length
len
from 2 to n
:- For start index
i
from 0 to n - len
:- Let
j = i + len - 1
, and set dp[i][j] = INT_MAX
. - For each split
k
from i
to j - 1
:- Compute
leftCost = dp[i][k]
- Compute
rightCost = dp[k+1][j]
- Compute
mergeCost = sum(i, k, prefix) * sum(k+1, j, prefix)
- Update
dp[i][j] = min(dp[i][j], leftCost + rightCost + mergeCost)
- Return
dp[0][n-1]
as the minimum total cost
Below is given the implementation:
C++
#include <bits/stdc++.h>
using namespace std;
// function to calculate the
// sum from a[i] to a[j]
int sum(int i, int j, vector<int> &prefix) {
if (i == 0)
return prefix[j] % 100;
return (prefix[j] - prefix[i - 1]) % 100;
}
int minCost(vector<int> &arr) {
int n = arr.size();
// initialize the dp
vector<vector<int>> dp(n, vector<int>(n, 0));
// to store prefix sum
vector<int> prefix(n);
prefix[0] = arr[0];
for(int i = 1; i < n; i++) {
prefix[i] = arr[i] + prefix[i - 1];
}
// Filling the dp array using tabulation
for (int len = 2; len <= n; len++) {
for (int i = 0; i < n - len + 1; i++) {
int j = i + len - 1;
dp[i][j] = INT_MAX;
for (int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j], (dp[i][k] + dp[k + 1][j] +
(sum(i, k, prefix) * sum(k + 1, j, prefix))));
}
}
}
// Return the minimum sum
return dp[0][n - 1];
}
int main() {
vector<int> arr = {40, 60, 20};
cout << minCost(arr);
return 0;
}
Java
import java.util.*;
public class GfG {
// function to calculate the
// sum from a[i] to a[j]
public static int sum(int i, int j, List<Integer> prefix) {
if (i == 0)
return prefix.get(j) % 100;
return (prefix.get(j) - prefix.get(i - 1)) % 100;
}
public static int minCost(List<Integer> arr) {
int n = arr.size();
// initialize the dp
int[][] dp = new int[n][n];
// to store prefix sum
List<Integer> prefix = new ArrayList<>();
prefix.add(arr.get(0));
for (int i = 1; i < n; i++) {
prefix.add(arr.get(i) + prefix.get(i - 1));
}
// Filling the dp array using tabulation
for (int len = 2; len <= n; len++) {
for (int i = 0; i < n - len + 1; i++) {
int j = i + len - 1;
dp[i][j] = Integer.MAX_VALUE;
for (int k = i; k < j; k++) {
dp[i][j] = Math.min(dp[i][j], (dp[i][k] + dp[k + 1][j] +
(sum(i, k, prefix) * sum(k + 1, j, prefix))));
}
}
}
// Return the minimum sum
return dp[0][n - 1];
}
public static void main(String[] args) {
List<Integer> arr = Arrays.asList(40, 60, 20);
System.out.print(minCost(arr));
}
}
Python
# function to calculate the
# sum from a[i] to a[j]
def sum(i, j, prefix):
if i == 0:
return prefix[j] % 100
return (prefix[j] - prefix[i - 1]) % 100
def minCost(arr):
n = len(arr)
# initialize the dp
dp = [[0] * n for _ in range(n)]
# to store prefix sum
prefix = [0] * n
prefix[0] = arr[0]
for i in range(1, n):
prefix[i] = arr[i] + prefix[i - 1]
# Filling the dp array using tabulation
for len1 in range(2, n + 1):
for i in range(0, n - len1 + 1):
j = i + len1 - 1
dp[i][j] = float('inf')
for k in range(i, j):
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] +
(sum(i, k, prefix) * sum(k + 1, j, prefix)))
# Return the minimum sum
return dp[0][n - 1]
if __name__ == "__main__":
arr = [40, 60, 20]
print(minCost(arr))
C#
using System;
using System.Collections.Generic;
public class GfG {
// function to calculate the
// sum from a[i] to a[j]
public static int sum(int i, int j, List<int> prefix) {
if (i == 0)
return prefix[j] % 100;
return (prefix[j] - prefix[i - 1]) % 100;
}
public static int minCost(List<int> arr) {
int n = arr.Count;
// initialize the dp
int[,] dp = new int[n, n];
// to store prefix sum
List<int> prefix = new List<int>();
prefix.Add(arr[0]);
for (int i = 1; i < n; i++) {
prefix.Add(arr[i] + prefix[i - 1]);
}
// Filling the dp array using tabulation
for (int len = 2; len <= n; len++) {
for (int i = 0; i < n - len + 1; i++) {
int j = i + len - 1;
dp[i, j] = int.MaxValue;
for (int k = i; k < j; k++) {
dp[i, j] = Math.Min(dp[i, j], dp[i, k] + dp[k + 1, j] +
(sum(i, k, prefix) * sum(k + 1, j, prefix)));
}
}
}
// Return the minimum sum
return dp[0, n - 1];
}
public static void Main() {
List<int> arr = new List<int> {40, 60, 20};
Console.Write(minCost(arr));
}
}
JavaScript
// function to calculate the
// sum from a[i] to a[j]
function sum(i, j, prefix) {
if (i === 0)
return prefix[j] % 100;
return (prefix[j] - prefix[i - 1]) % 100;
}
function minCost(arr) {
let n = arr.length;
// initialize the dp
let dp = Array.from({ length: n }, () => Array(n).fill(0));
// to store prefix sum
let prefix = new Array(n);
prefix[0] = arr[0];
for (let i = 1; i < n; i++) {
prefix[i] = arr[i] + prefix[i - 1];
}
// Filling the dp array using tabulation
for (let len = 2; len <= n; len++) {
for (let i = 0; i < n - len + 1; i++) {
let j = i + len - 1;
dp[i][j] = Number.MAX_SAFE_INTEGER;
for (let k = i; k < j; k++) {
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j] +
(sum(i, k, prefix) * sum(k + 1, j, prefix)));
}
}
}
// Return the minimum sum
return dp[0][n - 1];
}
let arr = [40, 60, 20];
console.log(minCost(arr));
Similar Reads
Matrix Chain Multiplication Given the dimension of a sequence of matrices in an array arr[], where the dimension of the ith matrix is (arr[i-1] * arr[i]), the task is to find the most efficient way to multiply these matrices together such that the total number of element multiplications is minimum. When two matrices of size m*
15+ min read
Matrix Chain Multiplication (A O(N^2) Solution) Given an array arr[] of size n, which represents the chain of matrices such that the ith matrix Ai is of dimension arr[i-1] x arr[i]. The task is to find the minimum number of multiplications needed to multiply the chain. Example:Input: arr[] = [40, 20, 30, 10, 30]Output: 26000 Explanation: There ar
6 min read
Printing brackets in Matrix Chain Multiplication Problem Given an array arr[] which represents the chain of matrices such that the dimensions of the ith matrix are arr[i-1] x arr[i]. The task is to find the correct parenthesis of the matrices such that when we multiply all the matrices together, the cost or total number of element multiplications is minim
15+ min read
Python Program for Matrix Chain Multiplication | DP-8 Given a sequence of matrices, find the most efficient way to multiply these matrices together. The problem is not actually to perform the multiplications, but merely to decide in which order to perform the multiplications. We have many options to multiply a chain of matrices because matrix multiplic
5 min read
Printing Matrix Chain Multiplication (A Space Optimized Solution) Prerequisite : Dynamic Programming | Set 8 (Matrix Chain Multiplication)Given a sequence of matrices, find the most efficient way to multiply these matrices together. The problem is not actually to perform the multiplications, but merely to decide in which order to perform the multiplications. We ha
12 min read
Minimum sum of multiplications of n numbers Given an integer array arr[] of length n. Your goal is to reduce the array to a single element by repeatedly applying the following operationSelect any two adjacent elements, call them x and y.Remove x and y from the array.Insert a new element equal to (x + y) mod 100 at their position.The cost of t
14 min read