Language: C++

#include <bits/stdc++.h>

using namespace std;
#define PB push_back
#define MP make_pair
#define LL long long
#define int LL
#define FOR(i,a,b) for(int i = (a); i <= (b); i++)
#define RE(i,n) FOR(i,1,n)
#define REP(i,n) FOR(i,0,(int)(n)-1)
#define R(i,n) REP(i,n)
#define VI vector<int>
#define PII pair<int,int>
#define LD long double
#define FI first
#define SE second
#define st FI
#define nd SE
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())

template<class C> void mini(C& _a4, C _b4) { _a4 = min(_a4, _b4); }
template<class C> void maxi(C& _a4, C _b4) { _a4 = max(_a4, _b4); }

template<class TH> void _dbg(const char *sdbg, TH h){ cerr<<sdbg<<'='<<h<<endl; }
template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while(*sdbg!=',')cerr<<*sdbg++;cerr<<'='<<h<<','; _dbg(sdbg+1, a...);
}

template<class T> ostream& operator<<(ostream& os, vector<T> V) {
  os << "["; for (auto& vv : V) os << vv << ","; os << "]";
  return os;
}

#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (__VA_ARGS__)
#define cerr if(0)cout
#endif

const LD kPi = 2 * acos(0);
struct CD {
  LD re, im;
  CD operator=(LD a) { re = a; im = 0; return *this; }
  CD operator*(CD& z) { return {re * z.re - im * z.im, re * z.im + im * z.re}; }
  void operator*=(CD& z) { *this = (*this * z); }
  CD operator+(CD& z) { return {re + z.re, im + z.im}; }
  CD operator-(CD& z) { return {re - z.re, im - z.im}; }
  void operator/=(LD f) { re /= f; im /= f; }
};

struct FFT {
private:
  CD *A, *B, *tmp, *res, *omega;
  int *rev_perm;
  int max_dep;
  // not needed if this is going to be used just once
  void Clear(int n) {
    REP (i, n) { A[i] = B[i] = res[i] = tmp[i] = 0; }
  }

  void fft(CD* from, CD* to, int depth, bool inv){
    int N = (1 << depth);
    REP (i, N) { to[rev_perm[i] >> (max_dep - depth)] = from[i]; }

    RE (m, depth) {
      int step = (1 << m);
      for (int pos = 0; pos < N; pos += step){
        int cur = 0;
        int delta = (1 << (max_dep - m));
        if (!inv) { cur = (1 << max_dep); delta *= -1; }
        REP (k, step / 2) {
          CD a = to[pos + k],
             b = omega[cur] * to[pos + k + step / 2];
          to[pos + k] = a + b;
          to[pos + k + step / 2] = a - b;
          cur += delta;
        }
      }
    }
    if (inv) { REP (i, N) { to[i] /= N; } }
  }
  
public:
  FFT(int max_deg) { // max degree of a polynomial given as input
    max_dep = 0;
    while ((1 << max_dep) <= 2 * max_deg) { max_dep++; }
    max_deg = (1 << max_dep) + 20;
    A = new CD[max_deg]; B = new CD[max_deg];
    res = new CD[max_deg]; tmp = new CD[max_deg];
    omega = new CD[max_deg]; rev_perm = new int[max_deg];
    int N = (1 << max_dep);
    LD ang = 2 * kPi / N;
    REP (i, N + 1) { omega[i] = {cos(i * ang), sin(i * ang)}; }
    rev_perm[0] = 0;
    int h = -1;
    RE (i, N) {
      if ((i & (i - 1)) == 0) { h++; }
      rev_perm[i] = rev_perm[i ^ (1 << h)] | (1 << (max_dep - h - 1));
    }
  }
  VI mul_less_exact(VI Q, VI R, int P) {
    int depth = 0, size = 1;
    int N = SZ(Q) + SZ(R) - 1;
    while (size < N) { depth++; size *= 2; }
    Clear(size);
    // start miejsca, w ktorym jak mozna mniejsza dokladnosc, to zmien na komentarze
    // P,Q \in R[x], A = Q * (1+i)/2 + R * (1-i)/2 -> Re(A^2) = P*Q
    REP (i, SZ(Q)) {
      //A[i] = CD{.5 * Q[i], .5 * Q[i]};
      A[i] = Q[i];
    }
    REP (i, SZ(R)) {
      //A[i] = A[i] + CD{.5 * R[i], -.5 * R[i]};
      B[i] = R[i];
    }
    //fft(A, tmp, depth, false);
    //REP (i, size) tmp[i] *= tmp[i];
    fft(A, res, depth, false);
    fft(B, tmp, depth, false);
    REP (i, size) tmp[i] *= res[i];
    // koniec
    fft(tmp, res, depth, true);
    VI ans;
    REP (i, N) { ans.PB((long long)round(res[i].re) % P); }
    return ans;
  }
  
  VI Prepare(VI& v, int base, int b_pow) {
    VI ans;
    for (int x : v) { ans.PB(b_pow ? x / base : x % base); }
    return ans;
  }
  int Sum(VI& v, int P) { // debug/assert purposes only
    return accumulate(ALL(v), 0LL) % P;
  }
  VI mul_exact(VI Q, VI R, int P) {
    int base = 32000;
    int pows[] = {1, base, (int)1LL * base * base % P};
    VI ans(SZ(Q) + SZ(R) - 1);
    REP (q, 2) {
      VI W = Prepare(Q, base, q);
      REP (r, 2) {
        VI V = Prepare(R, base, r);
        // jezeli bedzie za wolno, to można policzyc tylko 4 transformaty w przod
        // bo teraz dla kazdej z 4 czesci jest liczona podwojnie (przyspieszenie * 2/3)
        VI C = mul_less_exact(W, V, P);
        REP (i, SZ(C)) { ans[i] = (ans[i] + 1LL * C[i] * pows[q + r]) % P; }
      }
    }
    debug(Sum(ans, P), 1LL * Sum(Q, P) * Sum(R, P) % P);    // DEBUG!!
    assert(Sum(ans, P) == 1LL * Sum(Q, P) * Sum(R, P) % P); // DEBUG!!
    return ans;
  }
};

int P = 1e9 + 7;
int pot(int a,int w){
  int r = 1;
  while(w){
    if(w&1)
      r = r * a % P;
    w /= 2;
    a =  a * a % P;
  }
  return r;
}
int odw(int a){
  return pot(a,P-2);
}
const int MAX = 4e5;
int sil[MAX];
int a,b,c;
FFT fft(int(1e5)+2);
int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(11);
  cerr << fixed << setprecision(6);
  sil[0] = 1;
  for(int i = 1; i < MAX; i++)
    sil[i] = sil[i-1] * i % P;
  cin >> a >> b >> c;
  vector<int> x,y;
  R(i,b+1){
    x.PB(odw(sil[b-i]));
  }
  R(i,c+1){
    y.PB(odw(sil[c-i]));
  }
  debug(x,y);
  vector<int> spl = fft.mul_exact(x,y,P);
  debug(spl);
  int res = 0;
  int mn = odw(sil[a-1]);
  R(i,SZ(spl)){
    debug(sil[a-1+b+c-i], mn,spl[i]);
    res += sil[a-1+b+c-i] * mn % P * spl[i] % P;
    debug(res);
    mn*=3;
    mn%=P;
  }
  cout << res%P << endl;
}


Compiler output:
a.cc:6:12: error: expected primary-expression before 'long'
    6 | #define LL long long
      |            ^~~~
a.cc:7:13: note: in expansion of macro 'LL'
    7 | #define int LL
      |             ^~
a.cc:175:9: note: in expansion of macro 'int'
  175 | FFT fft(int(1e5)+2);
      |         ^~~