use std::str::FromStr;
use std::io::*;
use std::cmp::*;
use utils::*;

pub fn main() {
    let i = stdin();
    let mut o = Vec::new();
    run(i.lock(), &mut o);
    stdout().write_all(&o).unwrap();
}

fn run<R: BufRead, W: Write>(i: R, o: &mut W) {
    let mut i = AtRead::from(i);
    let nmk = i.read3::<usize, usize, usize>();
    writeln!(o, "{}", solve(nmk)).unwrap();
}
fn solve(n: (usize, usize, usize)) -> usize {
    let mut pows = Vec::new();
    let mut p = ModInt(1);
    for _ in 0..n.1 + n.2 + 1 {
        pows.push(p);
        p *= 3;
    }

    let mut c_i012 = PascalsTriangleIter::<ModInt>::new(n.0 - 1);
    let mut c_i12 = PascalsTriangleIter::<ModInt>::new(0);

    let n_sum = n.0 + n.1 + n.2;
    let mut result = ModInt(0);
    for i012 in n.0 - 1..n_sum {
        let i12 = i012 - (n.0 - 1);
        let mut c = ModInt(0);
        for i1 in 0..min(n.1, i12) + 1 {
            let i2 = i12 - i1;
            if i2 > n.2 {
                continue;
            }
            c += c_i12.get()[i1];
        }
        c *= c_i012.get()[n.0 - 1];
        c *= pows[n_sum - 1 - i012];
        result += c;

        c_i012.next();
        c_i12.next();
    }
    result.0
}

mod utils {
    #![allow(dead_code)]
    use super::*;
    use std::ops::*;

    pub struct AtRead<R: BufRead> {
        r: R,
        s: String,
    }

    macro_rules! fn_read {
        {$f:ident($($v:ident: $t:ident),*)} => {
            pub fn $f<$($t: FromStr),*>(&mut self) -> ($($t),*) {
                let i = &mut self.read_line().split(' ');
                $(
                    let $v = next(i);
                )*
                ($($v),*)
            }
        };
    }

    impl<R: BufRead> AtRead<R> {
        pub fn from(r: R) -> Self {
            AtRead {
                r: r,
                s: String::new(),
            }
        }
        pub fn read_line(&mut self) -> &str {
            self.s.clear();
            self.r.read_line(&mut self.s).unwrap();
            self.s.trim()
        }

        pub fn read<T: FromStr>(&mut self) -> T {
            self.read_line().parse().ok().unwrap()
        }
        fn_read! { read2(v1: T1, v2: T2) }
        fn_read! { read3(v1: T1, v2: T2, v3: T3) }
        fn_read! { read4(v1: T1, v2: T2, v3: T3, v4: T4) }

        pub fn read_vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            self.read_line()
                .split(' ')
                .take(n)
                .map(|x| x.parse().ok().unwrap())
                .collect()
        }
    }

    fn next<'a, T: FromStr, I: std::iter::Iterator<Item = &'a str>>(i: &mut I) -> T {
        i.next().unwrap().parse().ok().unwrap()
    }

    #[derive(Debug, Clone, Copy)]
    pub struct ModInt(pub usize);

    const MOD_BASE: usize = 1000000007;
    const MOD_INV_POW: usize = 1000000005;

    impl ModInt {
        pub fn new(n: usize) -> Self {
            ModInt(n % MOD_BASE)
        }
        pub fn pow(self, mut exp: usize) -> ModInt {
            let mut b = self;
            let mut r = ModInt(1);
            while exp != 0 {
                if exp % 2 == 1 {
                    r *= b;
                }
                exp /= 2;
                b = b * b;
            }
            r
        }
        pub fn inverse_element(self) -> ModInt {
            self.pow(MOD_INV_POW)
        }
    }

    macro_rules! ModInt_op {
        (($ot:ident, $f:ident), ($ot_a:ident, $f_a:ident), $($rhs:ty, $e:expr,)*) => {
            $(
            impl $ot<$rhs> for ModInt {
                type Output = Self;
                fn $f(self, rhs: $rhs) -> Self {
                    Self::new(($e)(self, rhs))
                }
            }
            impl $ot_a<$rhs> for ModInt {
                fn $f_a(&mut self, rhs: $rhs) {
                    *self = Self::new(($e)(*self, rhs))
                }
            }
            )*
        }
    }

    ModInt_op!(
        (Add, add),
        (AddAssign, add_assign),
        ModInt,
        |l: ModInt, r: ModInt| l.0 + r.0,
        usize,
        |l: ModInt, r: usize| l.0 + r,
    );

    ModInt_op!(
        (Mul, mul),
        (MulAssign, mul_assign),
        ModInt,
        |l: ModInt, r: ModInt| l.0 * r.0,
        usize,
        |l: ModInt, r: usize| l.0 * r,
    );

    ModInt_op!(
        (Sub, sub),
        (SubAssign, sub_assign),
        ModInt,
        |l: ModInt, r: ModInt| MOD_BASE + l.0 - r.0,
        usize,
        |l: ModInt, r: usize| MOD_BASE + l.0 - r,
    );

    // std::cmp::Reverseと同じ
    #[derive(PartialEq, Eq)]
    pub struct RevCmp<T>(pub T);

    impl<T: PartialOrd> PartialOrd for RevCmp<T> {
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
            other.0.partial_cmp(&self.0)
        }
    }
    impl<T: Ord> Ord for RevCmp<T> {
        fn cmp(&self, other: &Self) -> Ordering {
            other.0.cmp(&self.0)
        }
    }

    pub struct PascalsTriangle<T> {
        buf: Vec<T>,
        n: usize,
    }

    impl<T: One> PascalsTriangle<T> {
        pub fn new() -> Self {
            PascalsTriangle {
                buf: vec![T::one()],
                n: 1,
            }
        }
        pub fn get(&mut self, n: usize, m: usize) -> T {
            assert!(m <= n);
            self.ready(n);
            self.buf[n * (n + 1) / 2 + m]
        }

        pub fn ready(&mut self, n: usize) {
            while self.n <= n {
                let i = self.buf.len() - self.n;
                self.buf.push(T::one());
                for m in 1..self.n {
                    let v = self.buf[i + m - 1] + self.buf[i + m];
                    self.buf.push(v);
                }
                self.buf.push(T::one());
                self.n += 1;
            }
        }
    }

    pub struct PascalsTriangleIter<T> {
        buf: Vec<T>,
    }
    impl<T: One> PascalsTriangleIter<T> {
        pub fn new(n: usize) -> Self {
            let mut s = PascalsTriangleIter {
                buf: vec![T::one()],
            };
            for _ in 0..n {
                s.next();
            }
            s
        }
        pub fn next(&mut self) -> &[T] {
            for i in (1..self.buf.len()).rev() {
                self.buf[i] = self.buf[i] + self.buf[i - 1];
            }
            self.buf.push(T::one());
            self.get()
        }
        pub fn get(&self) -> &[T] {
            &self.buf
        }
    }

    pub trait Zero: Add<Output = Self> + Sized + Copy {
        fn zero() -> Self;
    }
    pub trait One: Zero {
        fn one() -> Self;
    }

    macro_rules! impl_zero {
        ($t:ty, $e:expr) => {
            impl Zero for $t {
                fn zero() -> Self {
                    $e
                }
            }
        }
    }
    macro_rules! impl_one {
        ($t:ty, $e1:expr, $e0:expr) => {
            impl One for $t {
                fn one() -> Self {
                    $e1
                }
            }
            impl_zero!($t, $e0);
        }
    }

    impl_one!(usize, 1, 0);
    impl_one!(u32, 1, 0);
    impl_one!(i32, 1, 0);
    impl_one!(f64, 1.0, 0.0);
    impl_one!(ModInt, ModInt(1), ModInt(0));

}
