Problem:
Score : 100 points

Problem Statement

There are N slimes lining up in a row.
Initially, the i-th slime from the left has a size of a_i.

Taro is trying to combine all the slimes into a larger slime.
He will perform the following operation repeatedly until there is only one slime:

Choose two adjacent slimes, and combine them into a new slime. The new slime has a size of x + y, where x and y are the sizes of the slimes before combining them. Here, a cost of x + y is incurred. The positional relationship of the slimes does not change while combining slimes.

Find the minimum possible total cost incurred.

Constraints

All values in input are integers.

2 \leq N \leq 400

1 \leq a_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 \ldots a_N

Output

Print the minimum possible total cost incurred.

Sample Input 1

4
10 20 30 40

Sample Output 1

190

Taro should do as follows (slimes being combined are shown in bold):

(10, 20, 30, 40) → (30, 30, 40)

(30, 30, 40) → (60, 40)

(60, 40) → (100)

Sample Input 2

5
10 10 10 10 10

Sample Output 2

120

Taro should do, for example, as follows:

(10, 10, 10, 10, 10) → (20, 10, 10, 10)

(20, 10, 10, 10) → (20, 20, 10)

(20, 20, 10) → (20, 30)

(20, 30) → (50)

Sample Input 3

3
1000000000 1000000000 1000000000

Sample Output 3

5000000000

The answer may not fit into a 32-bit integer type.

Sample Input 4

6
7 6 8 6 1 1

Sample Output 4

68

Taro should do, for example, as follows:

(7, 6, 8, 6, 1, 1) → (7, 6, 8, 6, 2)

(7, 6, 8, 6, 2) → (7, 6, 8, 8)

(7, 6, 8, 8) → (13, 8, 8)

(13, 8, 8) → (13, 16)

(13, 16) → (29)

Solution in Rust (1.15.1) (judge verdict: Accepted)

// This code is generated by [cargo-atcoder](https://github.com/tanakh/cargo-atcoder)
// Original source code:
/*
#![allow(unused_imports)]

use proconio::{input, fastout};
use proconio::marker::*;
use smallvec::alloc::collections::BinaryHeap;
use std::cmp::Reverse;
use nalgebra::min;

#[derive(Clone)]
pub struct BinaryIndexedTree<T> {
    sum_tree: Vec<T>,

}


impl<T: num_traits::identities::Zero +
std::ops::AddAssign +
std::ops::Sub<Output=T> +
std::ops::SubAssign +
std::marker::Copy>
BinaryIndexedTree<T> {
    pub fn new_size(len: usize) -> Self {
        Self { sum_tree: vec![T::zero(); len] }
    }


    pub fn new_array(vals: &[T]) -> Self {
        let mut sumtree = vals.to_vec();
        for i in 0..sumtree.len() {
            let mut val = sumtree[i];
            // For each consecutive 1 in the lowest order bits of i
            let mut j: usize = 1;
            while i & j != 0 {
                val += sumtree[i ^ j];
                j <<= 1;
            }
            sumtree[i] = val;
        }
        Self { sum_tree: sumtree }
    }


    pub fn len(&self) -> usize {
        self.sum_tree.len()
    }


    pub fn get(&self, index: usize) -> T {
        assert!(index < self.len());
        let mut result: T = self.sum_tree[index];
        let mut i: usize = 1;
        while index & i != 0 {
            result -= self.sum_tree[index ^ i];
            i <<= 1;
        }
        result
    }


    pub fn set(&mut self, index: usize, val: T) {
        assert!(index < self.len());
        let temp = self.get(index);
        self.sum_tree[index] = self.sum_tree[index] - temp + val;
    }


    pub fn add(&mut self, mut index: usize, delta: T) {
        assert!(index < self.len());
        loop {
            self.sum_tree[index] += delta;
            index |= index + 1;
            if index >= self.len() {
                break;
            }
        }
    }


    pub fn get_total(&self) -> T {
        self.get_prefix_sum(self.len())
    }


    pub fn get_prefix_sum(&self, mut end: usize) -> T {
        assert!(end <= self.len());
        let mut result = T::zero();
        while end > 0 {
            result += self.sum_tree[end - 1];
            end &= end - 1;
        }
        result
    }


    pub fn get_range_sum(&self, start: usize, end: usize) -> T {
        assert!(start <= end && end <= self.len());
        self.get_prefix_sum(end) - self.get_prefix_sum(start)
    }
}

#[fastout]
fn main() {
    input! {
    n: usize,
    a: [usize; n]
    }
    let mut dp = vec![vec![0; n + 1]; n + 1];
    let b = BinaryIndexedTree::new_array(&a);
    for l in (0..n).rev() {
        for r in (l + 1)..(n + 1) {
            if r - l == 1 {
                continue;
            }
            let mut t = usize::MAX;
            for m in (l + 1)..r {
                t = min(t, dp[l][m] + dp[m][r]);
            }
            dp[l][r] = t + b.get_range_sum(l, r);
        }
    }
    let ans = dp[0][n];
    println!("{}", ans);
}
*/

fn main() {
    let exe = "/tmp/bin7B985F54";
    std::io::Write::write_all(&mut std::fs::File::create(exe).unwrap(), &decode(BIN)).unwrap();
    std::fs::set_permissions(exe, std::os::unix::fs::PermissionsExt::from_mode(0o755)).unwrap();
    std::process::exit(std::process::Command::new(exe).status().unwrap().code().unwrap())
}

fn decode(v: &str) -> Vec<u8> {
    let mut ret = vec![];
    let mut buf = 0;
    let mut tbl = vec![64; 256];
    for i in 0..64 { tbl[TBL[i] as usize] = i as u8; }
    for (i, c) in v.bytes().filter_map(|c| { let c = tbl[c as usize]; if c < 64 { Some(c) } else { None } }).enumerate() {
        match i % 4 {
            0 => buf = c << 2,
            1 => { ret.push(buf | c >> 4); buf = c << 4; }
            2 => { ret.push(buf | c >> 2); buf = c << 6; }
            3 => ret.push(buf | c),
            _ => unreachable!(),
        }
    }
    ret
}

const TBL: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const BIN: &'static str = "<base64-encoded ELF executable removed>";