# Minimum sum of multiplications of n numbers

Given n integers. The task is to minimize the sum of multiplication of all the numbers by taking two adjacent numbers at a time and putting back their sum % 100 till a number is left.

Examples :

`Input : 40 60 20 Output : 2400  Explanation: There are two possible cases:1st possibility: Take 40 and 60, so multiplication=2400and put back (60+40) % 100 = 0, making it 0, 20.Multiplying 0 and 20 we get 0 so multiplication = 2400+0 = 2400. Put back (0+20)%100 = 20. 2nd possibility: take 60 and 20, so 60*20 = 1200,put back (60+20)%100 = 80, making it [40, 80] multiply 40*80 to get 3200, so multiplicationsum = 1200+3200 = 4400. Put back (40+80)%100 = 20 Input : 5 6 Output : 30 Explanation: Only possibility is 5*6=30 `

Approach: The problem is a variation of Matrix chain Multiplication Dynamic Programming

The idea is to partition N numbers into every possible value of k. Solve recursively for smaller parts and add the multiplication and store the minimum of them. Since we are dividing it into k parts, for every DPi,j we will have k partitions i<=k<j , store the minimum of them. So we get the formula similar to Matrix chain Multiplication Dynamic Programming

`DPi,j = min(DPi,j , (DPi,k+DPk+1,j+(cumulative_sumi,k*cumulative_sumk+1,j) ) ) for every i<=k<j. `

Since many subproblems will be repeating, hence we use memoization to store the values in a nXn matrix.

Given below is the illustration of the above approach:

## C++

 `// CPP program to find the ``// minimum sum of multiplication``// of n numbers``#include ``using` `namespace` `std;` `// Used in recursive ``// memoized solution``long` `long` `dp[1000][1000];` `// function to calculate the cumulative ``// sum from a[i] to a[j]``long` `long` `sum(``int` `a[], ``int` `i, ``int` `j)``{     ``    ``long` `long` `ans = 0;``    ``for` `(``int` `m = i; m <= j; m++)     ``        ``ans = (ans + a[m]) % 100;``    ``return` `ans;``}` `long` `long` `solve(``int` `a[], ``int` `i, ``int` `j)``{``    ``// base case ``    ``if` `(i == j)``        ``return` `0; ``    ` `    ``// memoization, if the partition ``    ``// has been called before then ``    ``// return the stored value ``    ``if` `(dp[i][j] != -1)``        ``return` `dp[i][j];``    ` `    ``// store a max value ``    ``dp[i][j] = INT_MAX;``    ` `    ``// we break them into k partitions ``    ``for` `(``int` `k = i; k < j; k++)``    ``{``        ``// store the min of the ``        ``// formula thus obtained``        ``dp[i][j] = min(dp[i][j], (solve(a, i, k) +``                              ``solve(a, k + 1, j) + ``              ``(sum(a, i, k) * sum(a, k + 1, j))));``    ``}``    ` `    ``// return the minimum ``    ``return` `dp[i][j];``}` `void` `initialize(``int` `n)``{``    ``for` `(``int` `i = 0; i <= n; i++) ``        ``for` `(``int` `j = 0; j <= n; j++)``            ``dp[i][j] = -1;     ``}` `// Driver code ``int` `main() {``    ``int` `a[] = {40, 60, 20}; ``    ``int` `n = ``sizeof``(a) / ``sizeof``(a[0]);``    ``initialize(n);``    ``cout << solve(a, 0, n - 1) << endl;``    ``return` `0;``}`

## Java

 `// Java program to find the  ``// minimum sum of multiplication``// of n numbers``import` `java.io.*;``import` `java.math.*;`  `class` `GFG``{``    ` `    ``// Used in recursive``    ``// memoized solution``    ``static` `long` `dp[][] = ``new` `long``[``1000``][``1000``];``    ` `    ``// function to calculate the ``    ``// cumulative  sum from a[i] to a[j]``    ``static` `long` `sum(``int` `a[], ``int` `i, ``int` `j)``    ``{     ``        ``long` `ans = ``0``;``        ``for` `(``int` `m = i; m <= j; m++)     ``            ``ans = (ans + a[m]) % ``100``;``        ``return` `ans;``    ``}``    ` `    ``static` `long` `solve(``int` `a[], ``int` `i, ``int` `j)``    ``{``        ``// base case ``        ``if` `(i == j)``            ``return` `0``; ``        ` `        ``// memoization, if the partition ``        ``// has been called before then ``        ``// return the stored value ``        ``if` `(dp[i][j] != -``1``)``            ``return` `dp[i][j];``        ` `        ``// store a max value ``        ``dp[i][j] = ``100000000``;``        ` `        ``// we break them into k partitions ``        ``for` `(``int` `k = i; k < j; k++)``        ``{``            ``// store the min of the``            ``// formula thus obtained``            ``dp[i][j] = Math.min(dp[i][j], (solve(a, i, k) +``                                       ``solve(a, k + ``1``, j) + ``                        ``(sum(a, i, k) * sum(a, k + ``1``,j))));``        ``}``        ` `        ``// return the minimum ``        ``return` `dp[i][j];``    ``}``    ` `    ``static` `void` `initialize(``int` `n)``    ``{``        ``for` `(``int` `i = ``0``; i <= n; i++) ``            ``for` `(``int` `j = ``0``; j <= n; j++)``                ``dp[i][j] = -``1``;     ``    ``}``    ` `    ``// Driver code ``    ``public` `static` `void` `main(String args[]) ``    ``{``        ``int` `a[] = {``40``, ``60``, ``20``}; ``        ``int` `n = a.length;``        ``initialize(n);``        ``System.out.println(solve(a, ``0``, n - ``1``));``        ` `    ``}``}` `/*This code is contributed by Nikita Tiwari.*/`

## Python3

 `# Python3 program to find the ``# minimum sum of multiplication ``# of n numbers ` `import` `numpy as np``import` `sys` `# Used in recursive ``# memoized solution ``dp ``=` `np.zeros((``1000``,``1000``)) ` `# function to calculate the cumulative ``# sum from a[i] to a[j] ``def` `sum``(a, i, j) :``        ` `    ``ans ``=` `0``    ``for` `m ``in` `range``(i, j ``+` `1``) : ``        ``ans ``=` `(ans ``+` `a[m]) ``%` `100``        ` `    ``return` `ans`  `def` `solve(a, i, j) :` `    ``# base case ``    ``if` `(i ``=``=` `j) : ``        ``return` `0``    ` `    ``# memoization, if the partition ``    ``# has been called before then ``    ``# return the stored value ``    ``if` `(dp[i][j] !``=` `-``1``) :``                ` `        ``return` `dp[i][j] ``    ` `    ``# store a max value ``    ``dp[i][j] ``=` `sys.maxsize``    ` `    ``# we break them into k partitions ``    ``for` `k ``in` `range``(i, j) :``                ` `        ``# store the min of the ``        ``# formula thus obtained ``        ``dp[i][j] ``=` `min``(dp[i][j], (solve(a, i, k) ``+` `solve(a, k ``+` `1``, j) ``                                ``+` `(``sum``(a, i, k) ``*` `sum``(a, k ``+` `1``, j)))) ``    ` `    ``# return the minimum ``    ``return` `dp[i][j]`  `def` `initialize(n) :``        ` `    ``for` `i ``in` `range``(n ``+` `1``) :``        ``for` `j ``in` `range``(n ``+` `1``) :``            ``dp[i][j] ``=` `-``1`    `#Driver code ``if` `__name__ ``=``=` `"__main__"` `:``        ` `    ``a ``=` `[``40``, ``60``, ``20``]``    ``n ``=` `len``(a) ``    ``initialize(n)``    ``print``(``int``(solve(a, ``0``, n ``-` `1``))) ` `# This code is contributed by Ryuga`

## C#

 `// C# program to find the ``// minimum sum of multiplication ``// of n numbers``using` `System;` `class` `GFG ``{``    ` `    ``// Used in recursive ``    ``// memoized solution``    ``static` `long` `[,]dp = ``new` `long``[1000, 1000];``    ` `    ``// Function to calculate the cumulative ``    ``// sum from a[i] to a[j]``    ``static` `long` `sum(``int` `[]a, ``int` `i, ``int` `j)``    ``{ ``        ``long` `ans = 0;``        ``for` `(``int` `m = i; m <= j; m++) ``            ``ans = (ans + a[m]) % 100;``        ``return` `ans;``    ``}``    ` `    ``static` `long` `solve(``int` `[]a, ``int` `i, ``int` `j)``    ``{``        ``// base case ``        ``if` `(i == j)``            ``return` `0; ``        ` `        ``// memoization, if the partition ``        ``// has been called before then ``        ``// return the stored value ``        ``if` `(dp[i, j] != -1)``            ``return` `dp[i, j];``        ` `        ``// store a max value ``        ``dp[i, j] = 100000000;``        ` `        ``// we break them into k partitions ``        ``for` `(``int` `k = i; k < j; k++)``        ``{``            ``// store the min of the ``            ``// formula thus obtained``            ``dp[i, j] = Math.Min(dp[i, j], (solve(a, i, k) +``                                       ``solve(a, k + 1, j) + ``                       ``(sum(a, i, k) * sum(a, k + 1, j))));``        ``}``        ` `        ``// return the minimum ``        ``return` `dp[i, j];``    ``}``    ` `    ``static` `void` `initialize(``int` `n)``    ``{``        ``for` `(``int` `i = 0; i <= n; i++) ``            ``for` `(``int` `j = 0; j <= n; j++)``                ``dp[i, j] = -1; ``    ``}``    ` `    ``// Driver code ``    ``public` `static` `void` `Main() ``    ``{``        ``int` `[]a = {40, 60, 20}; ``        ``int` `n = a.Length;``        ``initialize(n);``        ``Console.WriteLine(solve(a, 0, n - 1));``        ` `    ``}``}` `// This code is contributed by vt_m.`

## Javascript

 ``

## PHP

 ``

Output
```2400

```

Time Complexity: O(n^3)
Auxiliary Space: O(n^2)

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

• Create a DP of size N*N to store the computations of subproblems.
• Initialize Dp with 0.
• Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
• Return the final solution stored in dp[0][n-1].

Implementation :

## C++

 `#include ``using` `namespace` `std;` `// function to calculate the cumulative``// sum from a[i] to a[j]``long` `long` `sum(``int` `a[], ``int` `i, ``int` `j)``{``    ``long` `long` `ans = 0;``    ``for` `(``int` `m = i; m <= j; m++)``        ``ans = (ans + a[m]) % 100;``    ``return` `ans;``}` `long` `long` `solve(``int` `a[], ``int` `n)``{``    ``long` `long` `dp[n][n];` `    ``// Initializing the dp array``    ``for` `(``int` `i = 0; i < n; i++) {``        ``for` `(``int` `j = 0; j < n; j++) {``            ``dp[i][j] = 0;``        ``}``    ``}` `    ``// 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(a, i, k) * sum(a, k + 1, j))));``            ``}``        ``}``    ``}` `    ``// Return the minimum sum``    ``return` `dp[0][n - 1];``}` `// Driver code``int` `main()``{``    ``int` `a[] = { 40, 60, 20 };``    ``int` `n = ``sizeof``(a) / ``sizeof``(a[0]);` `    ``cout << solve(a, n) << endl;` `    ``return` `0;``}`

## Java

 `import` `java.util.Arrays;` `public` `class` `GFG {` `    ``// Function to calculate the cumulative sum from a[i] to a[j]``    ``public` `static` `long` `sum(``int``[] a, ``int` `i, ``int` `j) {``        ``long` `ans = ``0``;``        ``for` `(``int` `m = i; m <= j; m++)``            ``ans = (ans + a[m]) % ``100``;``        ``return` `ans;``    ``}` `    ``public` `static` `long` `solve(``int``[] a, ``int` `n) {``        ``long``[][] dp = ``new` `long``[n][n];` `        ``// Initializing the dp array``        ``for` `(``int` `i = ``0``; i < n; i++) {``            ``Arrays.fill(dp[i], ``0``);``        ``}` `        ``// 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(a, i, k) * sum(a, k + ``1``, j))));``                ``}``            ``}``        ``}` `        ``// Return the minimum sum``        ``return` `dp[``0``][n - ``1``];``    ``}` `    ``// Driver code``    ``public` `static` `void` `main(String[] args) {``        ``int``[] a = { ``40``, ``60``, ``20` `};``        ``int` `n = a.length;` `        ``System.out.println(solve(a, n));``    ``}``}`

## Python3

 `def` `sum_arr(a, i, j):``    ``"""``    ``Function to calculate the cumulative sum from a[i] to a[j]``    ``"""``    ``ans ``=` `0``    ``for` `m ``in` `range``(i, j``+``1``):``        ``ans ``=` `(ans ``+` `a[m]) ``%` `100``    ``return` `ans`  `def` `solve(a, n):``    ``"""``    ``Function to find the minimum sum required to ``    ``multiply matrices in a given order``    ``"""``    ``# Initializing the dp array``    ``dp ``=` `[[``0``] ``*` `n ``for` `_ ``in` `range``(n)]` `    ``# Filling the dp array using tabulation``    ``for` `length ``in` `range``(``2``, n ``+` `1``):``        ``for` `i ``in` `range``(n ``-` `length ``+` `1``):``            ``j ``=` `i ``+` `length ``-` `1``            ``# Initialize the current cell with infinity to find the minimum sum later``            ``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_arr(a, i, k) ``*` `sum_arr(a, k ``+` `1``, j))))``                ``# Compute the cost of multiplying matrices from i to k and k+1 to j``                ``# Update the minimum sum if a lower cost is found` `    ``# Return the minimum sum``    ``return` `dp[``0``][n ``-` `1``]`  `# Driver code``a ``=` `[``40``, ``60``, ``20``]``n ``=` `len``(a)` `print``(solve(a, n))`

## C#

 `using` `System;` `namespace` `CumulativeSumExample {``class` `Program {``    ``// Function to calculate the cumulative``    ``// sum from a[i] to a[j]``    ``static` `long` `Sum(``int``[] a, ``int` `i, ``int` `j)``    ``{``        ``long` `ans = 0;``        ``for` `(``int` `m = i; m <= j; m++)``            ``ans = (ans + a[m]) % 100;``        ``return` `ans;``    ``}` `    ``static` `long` `Solve(``int``[] a, ``int` `n)``    ``{``        ``long``[, ] dp = ``new` `long``[n, n];` `        ``// Initializing the dp array``        ``for` `(``int` `i = 0; i < n; i++) {``            ``for` `(``int` `j = 0; j < n; j++) {``                ``dp[i, j] = 0;``            ``}``        ``}` `        ``// 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(a, i, k)``                                      ``* Sum(a, k + 1, j))));``                ``}``            ``}``        ``}` `        ``// Return the minimum sum``        ``return` `dp[0, n - 1];``    ``}` `    ``// Driver code``    ``static` `void` `Main(``string``[] args)``    ``{``        ``int``[] a = { 40, 60, 20 };``        ``int` `n = a.Length;` `        ``Console.WriteLine(Solve(a, n));``    ``}``}``}`

## Javascript

 `function` `sum(a, i, j) {``    ``let ans = 0;``    ``for` `(let m = i; m <= j; m++) {``        ``ans = (ans + a[m]) % 100;``    ``}``    ``return` `ans;``}` `function` `solve(a, n) {``    ``const dp = ``new` `Array(n).fill(0).map(() => ``new` `Array(n).fill(0));` `    ``// Filling the dp array using tabulation``    ``for` `(let len = 2; len <= n; len++) {``        ``for` `(let i = 0; i < n - len + 1; i++) {``            ``const j = i + len - 1;``            ``dp[i][j] = Number.MAX_VALUE;` `            ``for` `(let k = i; k < j; k++) {``                ``dp[i][j] = Math.min(``                    ``dp[i][j],``                    ``dp[i][k] + dp[k + 1][j] + sum(a, i, k) * sum(a, k + 1, j)``                ``);``            ``}``        ``}``    ``}` `    ``// Return the minimum sum``    ``return` `dp[0][n - 1];``}` `// Driver code``const a = [40, 60, 20];``const n = a.length;` `console.log(solve(a, n));``//This code is contributed by chinmaya121221`

Output
```2400

```

Time Complexity: O(n^3)
Auxiliary Space: O(n^2)