#ifndef __clang__
#pragma GCC optimize ("-O3")
#endif
#define _GLIBCXX_USE_CXX11_ABI 0
#include <stdio.h>
#include <bits/stdc++.h>

#define DESTRUCT2(p, a, b)                      \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);

#define DESTRUCT3(p, a, b, c)                   \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);

#define DESTRUCT4(p, a, b, c, d)                \
  auto a = get<0>(p);                           \
  auto b = get<1>(p);                           \
  auto c = get<2>(p);                           \
  auto d = get<3>(p);

#define FOR(i, n)     for(lli i = 0; i < (lli)(n); ++i)
#define FORU(i, j, k) for(lli i = (j); i <= (lli)(k); ++i)
#define FORD(i, j, k) for(lli i = (j); i >= (lli)(k); --i)

#define SQ(x) ((x)*(x))

#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define eb emplace_back

using namespace std;

template<typename... As>
struct tpl : public std::tuple<As...> {
  using std::tuple<As...>::tuple;

  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type const&
  x() const { return get<0>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<0, T>::type&
  x() { return get<0>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type const&
  y() const { return get<1>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<1, T>::type&
  y() { return get<1>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type const&
  z() const { return get<2>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<2, T>::type&
  z() { return get<2>(*this); }

  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type const&
  w() const { return get<3>(*this); }
  template<typename T = tuple<As...> >
  typename tuple_element<3, T>::type&
  w() { return get<3>(*this); }
};

using lli   = long long int;
using llu   = long long unsigned;

using pii   = tpl<lli, lli>;
using piii  = tpl<lli, lli, lli>;
using piiii = tpl<lli, lli, lli, lli>;
using vi    = vector<lli>;
using vii   = vector<pii>;
using viii  = vector<piii>;
using vvi   = vector<vi>;
using vvii  = vector<vii>;
using vviii = vector<viii>;

template<class T>
using min_queue = priority_queue<T, vector<T>, greater<T> >;
template<class T>
using max_queue = priority_queue<T>;

template<size_t... I>
struct my_index_sequence {
  using type = my_index_sequence;
  static constexpr array<size_t, sizeof...(I)> value = { {I...} };
};

namespace my_index_sequence_detail {
  template<typename I, typename J> struct concat;
  template<size_t... I, size_t... J>
  struct concat<my_index_sequence<I...>, my_index_sequence<J...> > :
    my_index_sequence<I..., (sizeof...(I)+J)...> { };
  template<size_t N> struct make_index_sequence :
    concat<typename make_index_sequence<N/2>::type, typename make_index_sequence<N-N/2>::type>::type { };
  template <> struct make_index_sequence<0> : my_index_sequence<>{};
  template <> struct make_index_sequence<1> : my_index_sequence<0>{};
}

template<class... A>
using my_index_sequence_for = typename my_index_sequence_detail::make_index_sequence<sizeof...(A)>::type;

template<class T, size_t... I>
void print_tuple(ostream& s, T const& a, my_index_sequence<I...>){
  using swallow = int[];
  (void)swallow{0, (void(s << (I == 0? "" : ", ") << get<I>(a)), 0)...};
}

template<class T>
ostream& print_collection(ostream& s, T const& a){
  s << '[';
  for(auto it = begin(a); it != end(a); ++it){
    s << *it;
    if(it != prev(end(a))) s << " ";
  }
  return s << ']';
}

template<class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a){
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}

template<class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a){
  return s << "(" << get<0>(a) << ", " << get<1>(a) << ")";
}

template<class T, size_t I>
ostream& operator<<(ostream& s, array<T, I> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, vector<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, multimap<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, multiset<T> const& a) { return print_collection(s, a); }
template<class T, class U>
ostream& operator<<(ostream& s, map<T, U> const& a) { return print_collection(s, a); }
template<class T>
ostream& operator<<(ostream& s, set<T> const& a) { return print_collection(s, a); }

namespace std {
  namespace {
    template <class T>
    inline void hash_combine(size_t& seed, T const& v) {
      seed ^= hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
    }
    template <class Tuple, size_t Index = tuple_size<Tuple>::value - 1>
    struct HashValueImpl {
      static void apply(size_t& seed, Tuple const& tuple) {
        HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
        hash_combine(seed, get<Index>(tuple));
      }
    };
    template <class Tuple>
    struct HashValueImpl<Tuple, 0> {
      static void apply(size_t& seed, Tuple const& tuple) {
        hash_combine(seed, get<0>(tuple));
      }
    };
  }
  template <typename ... TT>
  struct hash<tuple<TT...>> {
    size_t operator()(tuple<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tuple<TT...> >::apply(seed, tt);
      return seed;
    }
  };
  template <typename ... TT>
  struct hash<tpl<TT...>> {
    size_t operator()(tpl<TT...> const& tt) const {
      size_t seed = 0;
      HashValueImpl<tpl<TT...> >::apply(seed, tt);
      return seed;
    }
  };
}

//------------------------------------------------------------------------------

const lli MOD = 1e9+7;
lli cnk[3002][3002];
lli p3[1000001];

lli fexp(lli a, lli b) {
  if(b == 1) return a;
  lli c = fexp(a, b/2);
  c = (c*c)%MOD;
  if(b&1) c = (c*a)%MOD;
  return c;
}

lli invmod(lli a) {
  return fexp(a, MOD-2);
}

int main(int, char**){
  ios::sync_with_stdio(0); cin.tie(0);
  lli n, m, k; cin >> n >> m >> k;
  p3[0] = 1; FOR(i, 1000000) p3[i+1]=(3*p3[i])%MOD;
  FOR(i, 3000) {
    cnk[i][0] = 1;
    cnk[i][i] = 1;
    FORU(j, 1, i-1) cnk[i][j] = (cnk[i-1][j-1]+cnk[i-1][j])%MOD;
  }
  lli ans = 0;
  lli cur0 = 1;
  lli l0 = 0, l1 = 0;
  lli v0 = 1, v1 = 1;
  lli s0 = 0;
  FORU(i, n, n+m+k) {
    lli nl0 = max<lli>(0, i-n-m);
    lli nl1 = min<lli>(i-n, k);
    lli nv0, nv1;
    lli nv00, nv01;
    lli nv10, nv11;
    nv00 = (v0+((v0*(i-1-n-l0))%MOD)*invmod(nl0))%MOD;
    nv00 += MOD; nv00 %= MOD;
    nv01 = 1;
    if(nl0>l0) {
      nv0 = nv00;
    }else{
      nv0 = nv01;
    }
    nv10 = (v1+((v1*(i-1-n-l1))%MOD)*invmod(nl1))%MOD;
    nv10 += MOD; nv10 %= MOD;
    nv11 = (v1+((v1*invmod(i-n-l1))%MOD)*(l1))%MOD;
    nv11 += MOD; nv11 %= MOD;
    if(nl1>l1){
      nv1 = nv10;
    }else{
      nv1 = nv11;
    }
    if(nl0==nl1) s0 = 0;
    else if(nl0+1==nl1) {
      s0=nv1;
    } else {
      lli ns0 = s0+s0-v1+v0;
      ns0%=MOD;
      if(nl1>l1) ns0 += nv1;
      if(nl0>l0) ns0 -= nv0;
      ns0 %= MOD;
      ns0 += MOD;
      ns0 %= MOD;
      s0 = ns0;
    }
    // FORU(j, nl0, nl1) {
    //   s += cnk[i-n][j];
    // }
    lli s = nv0+s0;
    l0 = nl0; l1 = nl1;
    v0 = nv0; v1 = nv1;
    s %= MOD;
    s *= cur0;
    s %= MOD;
    s *= p3[n+m+k-i];
    s %= MOD;
    (ans += s) %= MOD;

    cur0 = cur0+((cur0*invmod(i-n+1))%MOD)*(n-1); cur0 %= MOD; cur0 += MOD; cur0 %= MOD;
  }
  cout << ans << endl;
  return 0;
}


Measured memory_bytes: 54272