// attr {{{
#![allow(
    dead_code,
    non_snake_case,
    unused_imports,
    //unused_macros,
)]
// }}}

// use {{{
use std::fmt;
use std::io::{self,BufRead,Read,Write};
use std::str;
// }}}

const INF: i64 = 1_010_000_000_000_000_000;
const MOD: i64 = 1_000_000_007;
const EPS: f64 = 1e-9;

// util {{{
fn abs_diff(a: i64, b: i64) -> i64 {
    if a < b { b-a } else { a-b }
}

fn is_even(n: i64) -> bool { n % 2 == 0 }
fn is_odd (n: i64) -> bool { n % 2 != 0 }

fn div_ceil(a: i64, b: i64) -> i64 {
    let up = ((a<0) ^ (b>0)) && (a%b != 0);
    a/b + if up { 1 } else { 0 }
}

fn div_floor(a: i64, b: i64) -> i64 {
    let down = ((a>0) ^ (b>0)) && (a%b != 0);
    a/b - if down { 1 } else { 0 }
}

fn modulo(a: i64, b: i64) -> i64 {
    assert!(b > 0);
    let r = a % b;
    if r >= 0 { r } else { r+b }
}

fn chmax(xmax: &mut i64, x: i64) -> bool {
    if x > *xmax {
        *xmax = x;
        true
    }
    else {
        false
    }
}

fn chmin(xmin: &mut i64, x: i64) -> bool {
    if x < *xmin {
        *xmin = x;
        true
    }
    else {
        false
    }
}

fn _gcd(a: i64, b: i64) -> i64 {
    if b == 0 { a } else { _gcd(b, a%b) }
}

fn gcd(v: &[i64]) -> i64 {
    debug_assert!(v.len() >= 1);
    v.iter().fold(0, |a,&b| _gcd(a,b))
}

fn lcm(v: &[i64]) -> i64 {
    debug_assert!(v.len() >= 1);
    v.iter().fold(1, |a,&b| a / _gcd(a,b) * b)
}

fn _INPUT() -> String {
    let mut res = String::new();
    io::stdin().read_to_string(&mut res).expect("read_to_string()");
    res
}

struct Reader<'a> {
    input: &'a String,
    tokens: str::SplitWhitespace<'a>,
}

impl<'a> Reader<'a> {
    pub fn new(input: &'a String) -> Reader {
        Reader {
            input: input,
            tokens: input.split_whitespace(),
        }
    }

    pub fn RD<T>(&mut self) -> T
        where T: str::FromStr,
              <T as str::FromStr>::Err: fmt::Debug
    {
        self.tokens.next().unwrap().parse().unwrap()
    }

    pub fn RD_VEC<T>(&mut self, n: i64) -> Vec<T>
        where T: str::FromStr,
              <T as str::FromStr>::Err: fmt::Debug
    {
        let mut res: Vec<T> = Vec::with_capacity(n as usize);
        for _ in 0..n {
            res.push(self.RD());
        }
        res
    }
}
// }}}

struct MatMul {
    pub R: Vec<i64>,
    pub C: Vec<i64>,

    done: [[bool; 100]; 100],
    memo: [[i64; 100]; 100],
}

impl MatMul {
    fn new(N: i64) -> Self {
        Self {
            R: vec![0; N as usize],
            C: vec![0; N as usize],
            done: [[false; 100]; 100],
            memo: [[0; 100]; 100],
        }
    }

    fn f(&mut self, i: i64, j: i64) -> i64 {
        assert!(i <= j);

        if i == j { return 0; }

        if !self.done[i as usize][j as usize] {
            self.memo[i as usize][j as usize] = INF;
            for k in i..j {
                let mut cnt: i64 = 0;
                cnt += self.f(i, k);
                cnt += self.f(k+1, j);
                cnt += self.R[i as usize] * self.C[k as usize] * self.C[j as usize];
                chmin(&mut self.memo[i as usize][j as usize], cnt);
            }

            self.done[i as usize][j as usize] = true;
        }

        self.memo[i as usize][j as usize]
    }
}

fn main() {
    // I/O {{{
    let _input = _INPUT();
    let mut _reader = Reader::new(&_input);
    macro_rules! RD {
        () => (_reader.RD());
    }
    macro_rules! RD_VEC {
        ($n:expr) => (_reader.RD_VEC($n));
    }

    let _stdout = io::stdout();
    let mut _stdout = _stdout.lock();
    macro_rules! PRINTLN {
        () => (writeln!(_stdout).unwrap());
        ($fmt:expr) => (writeln!(_stdout, $fmt).unwrap());
        ($fmt:expr, $($arg:tt)*) => (writeln!(_stdout, $fmt, $($arg)*).unwrap());
    }
    // }}}

    let N: i64 = RD!();

    let mut mm: MatMul = MatMul::new(N);
    for i in 0..N {
        mm.R[i as usize] = RD!();
        mm.C[i as usize] = RD!();
    }
    let ans = mm.f(0, N-1);
    PRINTLN!("{}", ans);
}



Measured memory_bytes: 5204