pub trait FromFragments: Sized {
    fn fragments_count() -> usize;
    fn from_fragments(fragments: &[&str]) -> Result<Self, String>;
}
impl FromFragments for () {
    fn fragments_count() -> usize {
        1
    }
    fn from_fragments(_fragments: &[&str]) -> Result<(), String> {
        Ok(())
    }
}
impl FromFragments for String {
    fn fragments_count() -> usize {
        1
    }
    fn from_fragments(fragments: &[&str]) -> Result<String, String> {
        Ok(fragments[0].to_string())
    }
}
macro_rules ! impl_from_fragments { ( $ ( $ t : ty ) * ) => { $ ( impl FromFragments for $ t { fn fragments_count ( ) -> usize { 1 } fn from_fragments ( fragments : & [ & str ] ) -> Result <$ t , String > { use std :: str :: FromStr ; <$ t >:: from_str ( fragments [ 0 ] ) . map_err ( | _ | { format ! ( "cannot parse \"{}\" as {}" , fragments [ 0 ] , stringify ! ( $ t ) ) } ) } } ) * } ; }
impl_from_fragments ! ( isize usize i8 u8 i16 u16 i32 u32 i64 u64 f32 f64 ) ;
pub trait FromLine: Sized {
    fn from_line(line: &str) -> Result<Self, String>;
}
fn split_into_fragments(line: &str) -> Vec<&str> {
    line.trim_right_matches('\n').split_whitespace().collect()
}
impl<T: FromFragments> FromLine for T {
    fn from_line(line: &str) -> Result<T, String> {
        let fragments = split_into_fragments(line);
        if fragments.len() != T::fragments_count() {
            return Err(format!(
                "line \"{}\" has {} fragments, expected {}",
                line,
                fragments.len(),
                T::fragments_count()
            ));
        }
        T::from_fragments(&fragments)
    }
}
impl<T: FromFragments> FromLine for Vec<T> {
    fn from_line(line: &str) -> Result<Vec<T>, String> {
        let n = T::fragments_count();
        let fragments = split_into_fragments(line);
        if fragments.len() % n != 0 {
            return Err(format!(
                "line \"{}\" has {} fragments, expected multiple of {}",
                line,
                fragments.len(),
                n
            ));
        }
        let mut result = Vec::new();
        for chunk in fragments.chunks(n) {
            match T::from_fragments(chunk) {
                Ok(v) => result.push(v),
                Err(msg) => {
                    let flagment_msg = if n == 1 {
                        format!("fragment {}", result.len())
                    } else {
                        let l = result.len();
                        format!("fragments {}-{}", n * l + 1, (n + 1) * l)
                    };
                    return Err(format!("{} of line \"{}\": {}", flagment_msg, line, msg));
                }
            }
        }
        Ok(result)
    }
}
macro_rules ! impl_from_fragments_for_tuples { ( $ t : ident $ var : ident $ count : expr ) => ( ) ; ( $ t : ident $ var : ident $ count : expr ; $ ( $ inner_t : ident $ inner_var : ident $ inner_count : expr ) ;* ) => { impl_from_fragments_for_tuples ! ( $ ( $ inner_t $ inner_var $ inner_count ) ;* ) ; impl <$ t : FromFragments , $ ( $ inner_t : FromFragments ) ,*> FromFragments for ( $ t , $ ( $ inner_t ) ,* ) { fn fragments_count ( ) -> usize { let mut n = <$ t >:: fragments_count ( ) ; $ ( n += <$ inner_t >:: fragments_count ( ) ; ) * n } # [ allow ( unused_assignments ) ] fn from_fragments ( fragments : & [ & str ] ) -> Result < ( $ t , $ ( $ inner_t ) ,* ) , String > { let mut start = 0 ; let $ var = <$ t >:: from_fragments ( & fragments [ start .. start +<$ t >:: fragments_count ( ) ] ) ?; start += <$ t >:: fragments_count ( ) ; $ ( let $ inner_var = <$ inner_t >:: from_fragments ( & fragments [ start .. start +<$ inner_t >:: fragments_count ( ) ] ) ?; start += <$ inner_t >:: fragments_count ( ) ; ) * Ok ( ( $ var , $ ( $ inner_var ) ,* ) ) } } } }
impl_from_fragments_for_tuples ! ( T4 x4 4 ; T3 x3 3 ; T2 x2 2 ; T1 x1 1 ) ;
#[macro_export]
macro_rules ! read { ( ) => { let mut line = String :: new ( ) ; std :: io :: stdin ( ) . read_line ( & mut line ) . unwrap ( ) ; } ; ( $ pat : pat = $ t : ty ) => { let mut line = String :: new ( ) ; std :: io :: stdin ( ) . read_line ( & mut line ) . unwrap ( ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; } ; ( $ ( $ pat : pat = $ t : ty ) ,+ ) => { read ! ( ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ) ; } ; }
#[macro_export]
macro_rules ! readls { ( $ ( $ pat : pat = $ t : ty ) ,+ ) => { $ ( read ! ( $ pat = $ t ) ; ) * } }
pub fn read_vec<T: FromLine>() -> Vec<T> {
    use std::io::{self, BufRead};
    let stdin = io::stdin();
    let result = stdin
        .lock()
        .lines()
        .map(|line_result| {
            let line = line_result.expect("read from stdin failed");
            T::from_line(&line).unwrap()
        })
        .collect();
    result
}
#[macro_export]
macro_rules ! read_loop { ( $ pat : pat = $ t : ty ; $ block : block ) => { use std :: io :: BufRead ; let stdin = std :: io :: stdin ( ) ; for line in stdin . lock ( ) . lines ( ) { let line = line . expect ( "read from stdin failed" ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; $ block } } ; ( $ ( $ pat : pat = $ t : ty ) ,* ; $ block : block ) => { read_loop ! ( ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ; $ block ) ; } }
#[macro_export]
macro_rules ! readn_loop { ( $ n : expr ; $ pat : pat = $ t : ty ; $ block : block ) => { use std :: io :: BufRead ; let stdin = std :: io :: stdin ( ) ; { let lock = stdin . lock ( ) ; for _ in 0 ..$ n { let line = String :: new ( ) ; lock . read_line ( & mut line ) . expect ( "read from stdin failed" ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; $ block } } } ; ( $ n : expr ; $ ( $ pat : pat = $ t : ty ) ,* ; $ block : block ) => { read_times_loop ! ( $ n ; ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ; $ block ) ; } }

fn main() {
    read!(ab = u16, bc = u16, _ = u16);
    println!("{}", ab * bc / 2);
}


Measured memory_bytes: 4352