Problem p04004 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

const long long INF = 1e18;
const ll mod = 1000000007;
template <int mod> struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while (n > 0) {
      if (n & 1)
        ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt<mod>;
namespace FastFourierTransform {
using real = double;

struct C {
  real x, y;

  C() : x(0), y(0) {}

  C(real x, real y) : x(x), y(y) {}

  inline C operator+(const C &c) const { return C(x + c.x, y + c.y); }

  inline C operator-(const C &c) const { return C(x - c.x, y - c.y); }

  inline C operator*(const C &c) const {
    return C(x * c.x - y * c.y, x * c.y + y * c.x);
  }

  inline C conj() const { return C(x, -y); }
};

const real PI = acosl(-1);
int base = 1;
vector<C> rts = {{0, 0}, {1, 0}};
vector<int> rev = {0, 1};

void ensure_base(int nbase) {
  if (nbase <= base)
    return;
  rev.resize(1 << nbase);
  rts.resize(1 << nbase);
  for (int i = 0; i < (1 << nbase); i++) {
    rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
  }
  while (base < nbase) {
    real angle = PI * 2.0 / (1 << (base + 1));
    for (int i = 1 << (base - 1); i < (1 << base); i++) {
      rts[i << 1] = rts[i];
      real angle_i = angle * (2 * i + 1 - (1 << base));
      rts[(i << 1) + 1] = C(cos(angle_i), sin(angle_i));
    }
    ++base;
  }
}

void fft(vector<C> &a, int n) {
  assert((n & (n - 1)) == 0);
  int zeros = __builtin_ctz(n);
  ensure_base(zeros);
  int shift = base - zeros;
  for (int i = 0; i < n; i++) {
    if (i < (rev[i] >> shift)) {
      swap(a[i], a[rev[i] >> shift]);
    }
  }
  for (int k = 1; k < n; k <<= 1) {
    for (int i = 0; i < n; i += 2 * k) {
      for (int j = 0; j < k; j++) {
        C z = a[i + j + k] * rts[j + k];
        a[i + j + k] = a[i + j] - z;
        a[i + j] = a[i + j] + z;
      }
    }
  }
}

vector<int64_t> multiply(const vector<int> &a, const vector<int> &b) {
  int need = (int)a.size() + (int)b.size() - 1;
  int nbase = 1;
  while ((1 << nbase) < need)
    nbase++;
  ensure_base(nbase);
  int sz = 1 << nbase;
  vector<C> fa(sz);
  for (int i = 0; i < sz; i++) {
    int x = (i < (int)a.size() ? a[i] : 0);
    int y = (i < (int)b.size() ? b[i] : 0);
    fa[i] = C(x, y);
  }
  fft(fa, sz);
  C r(0, -0.25 / (sz >> 1)), s(0, 1), t(0.5, 0);
  for (int i = 0; i <= (sz >> 1); i++) {
    int j = (sz - i) & (sz - 1);
    C z = (fa[j] * fa[j] - (fa[i] * fa[i]).conj()) * r;
    fa[j] = (fa[i] * fa[i] - (fa[j] * fa[j]).conj()) * r;
    fa[i] = z;
  }
  for (int i = 0; i < (sz >> 1); i++) {
    C A0 = (fa[i] + fa[i + (sz >> 1)]) * t;
    C A1 = (fa[i] - fa[i + (sz >> 1)]) * t * rts[(sz >> 1) + i];
    fa[i] = A0 + A1 * s;
  }
  fft(fa, sz >> 1);
  vector<int64_t> ret(need);
  for (int i = 0; i < need; i++) {
    ret[i] = llround(i & 1 ? fa[i >> 1].y : fa[i >> 1].x);
  }
  return ret;
}
}; // namespace FastFourierTransform
template <typename T> struct ArbitraryModConvolution {
  using real = FastFourierTransform::real;
  using C = FastFourierTransform::C;

  ArbitraryModConvolution() = default;

  vector<T> multiply(const vector<T> &a, const vector<T> &b, int need = -1) {
    if (need == -1)
      need = a.size() + b.size() - 1;
    int nbase = 0;
    while ((1 << nbase) < need)
      nbase++;
    FastFourierTransform::ensure_base(nbase);
    int sz = 1 << nbase;
    vector<C> fa(sz);
    for (int i = 0; i < a.size(); i++) {
      fa[i] = C(a[i].x & ((1 << 15) - 1), a[i].x >> 15);
    }
    fft(fa, sz);
    vector<C> fb(sz);
    if (a == b) {
      fb = fa;
    } else {
      for (int i = 0; i < b.size(); i++) {
        fb[i] = C(b[i].x & ((1 << 15) - 1), b[i].x >> 15);
      }
      fft(fb, sz);
    }
    real ratio = 0.25 / sz;
    C r2(0, -1), r3(ratio, 0), r4(0, -ratio), r5(0, 1);
    for (int i = 0; i <= (sz >> 1); i++) {
      int j = (sz - i) & (sz - 1);
      C a1 = (fa[i] + fa[j].conj());
      C a2 = (fa[i] - fa[j].conj()) * r2;
      C b1 = (fb[i] + fb[j].conj()) * r3;
      C b2 = (fb[i] - fb[j].conj()) * r4;
      if (i != j) {
        C c1 = (fa[j] + fa[i].conj());
        C c2 = (fa[j] - fa[i].conj()) * r2;
        C d1 = (fb[j] + fb[i].conj()) * r3;
        C d2 = (fb[j] - fb[i].conj()) * r4;
        fa[i] = c1 * d1 + c2 * d2 * r5;
        fb[i] = c1 * d2 + c2 * d1;
      }
      fa[j] = a1 * b1 + a2 * b2 * r5;
      fb[j] = a1 * b2 + a2 * b1;
    }
    fft(fa, sz);
    fft(fb, sz);
    vector<T> ret(need);
    for (int i = 0; i < need; i++) {
      int64_t aa = llround(fa[i].x);
      int64_t bb = llround(fb[i].x);
      int64_t cc = llround(fa[i].y);
      aa = T(aa).x, bb = T(bb).x, cc = T(cc).x;
      ret[i] = aa + (bb << 15) + (cc << 30);
    }
    return ret;
  }
};
vector<ll> inv, FactorialInv, Factorial;
ll beki(ll a, ll b) {
  ll ret = 1 % mod;
  a %= mod;
  while (b) {
    if (b & 1LL)
      ret = ret * a % mod;
    a = a * a % mod;
    b >>= 1;
  }
  return ret;
}
void init_combination(ll MAX) {
  Factorial.resize(MAX + 1);
  FactorialInv.resize(MAX + 1);
  inv.resize(MAX + 1);
  Factorial[0] = 1;
  inv[0] = 1;
  for (int i = 1; i <= MAX; i++) {
    Factorial[i] = Factorial[i - 1] * i % mod;
  }
  FactorialInv[MAX] = beki(Factorial[MAX], mod - 2);
  for (ll i = MAX - 1; i >= 0; i--) {
    FactorialInv[i] = FactorialInv[i + 1] * (i + 1) % mod;
  }
  for (int i = 1; i <= MAX; i++) {
    inv[i] = FactorialInv[i] * Factorial[i - 1] % mod;
  }
}
ll combination(ll a, ll b) {
  if ((a == b) || (b == 0)) {
    return 1;
  }
  if (a < b)
    return 0;
  if (b < 0)
    return 0;
  ll ans = Factorial[a] * FactorialInv[b] % mod;
  ans = ans * FactorialInv[a - b] % mod;
  return ans;
}
ll N, M, K;
modint f(ll M, ll K) {
  modint ret = 0;
  vector<modint> C;
  vector<modint> A(M + 1), B(K + 1);
  for (int i = 0; i <= M; i++) {
    A[i] = FactorialInv[i];
  }
  for (int i = 0; i <= K; i++) {
    B[i] = FactorialInv[i];
  }
  ArbitraryModConvolution<modint> NTT;
  C = NTT.multiply(A, B);
  for (int s = 0; s <= M + K; s++) {
    modint tmp1 = Factorial[N + s];
    tmp1 *= C[s];
    ret += tmp1 * beki(beki(3, mod - 2), s);
    // cerr << s << " " << tmp1 << " " << tmp2 << endl;
  }
  return ret;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  init_combination(1e7);
  cin >> N >> M >> K;
  modint ans = 0;
  /*
  for(int s = 0; s <= M + K; s++) {
      modint tmp1 = Factorial[N+s] * FactorialInv[N];
      tmp1 *= C[s];
      modint tmp2 = 0;
      if(s) {
          tmp2 = Factorial[N+s-1] * FactorialInv[N];
          tmp2 *= C[s-1];
          tmp2 *= 2;
      }
      modint tmp = (tmp1 - tmp2);
      ans += tmp * beki(3, M + K - s);
      cerr << s << " " << tmp1 << " " << tmp2 << endl;
  }
  */
  ans += f(M, K);
  cerr << ans << endl;
  ans -= f(M - 1, K) * beki(3, mod - 2);
  cerr << ans << endl;
  ans -= f(M, K - 1) * beki(3, mod - 2);
  cerr << ans << endl;
  ans *= FactorialInv[N];
  ans *= beki(3, M + K);
  cout << ans << endl;
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

const long long INF = 1e18;
const ll mod = 1000000007;
template <int mod> struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while (n > 0) {
      if (n & 1)
        ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt<mod>;
namespace FastFourierTransform {
using real = double;

struct C {
  real x, y;

  C() : x(0), y(0) {}

  C(real x, real y) : x(x), y(y) {}

  inline C operator+(const C &c) const { return C(x + c.x, y + c.y); }

  inline C operator-(const C &c) const { return C(x - c.x, y - c.y); }

  inline C operator*(const C &c) const {
    return C(x * c.x - y * c.y, x * c.y + y * c.x);
  }

  inline C conj() const { return C(x, -y); }
};

const real PI = acosl(-1);
int base = 1;
vector<C> rts = {{0, 0}, {1, 0}};
vector<int> rev = {0, 1};

void ensure_base(int nbase) {
  if (nbase <= base)
    return;
  rev.resize(1 << nbase);
  rts.resize(1 << nbase);
  for (int i = 0; i < (1 << nbase); i++) {
    rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
  }
  while (base < nbase) {
    real angle = PI * 2.0 / (1 << (base + 1));
    for (int i = 1 << (base - 1); i < (1 << base); i++) {
      rts[i << 1] = rts[i];
      real angle_i = angle * (2 * i + 1 - (1 << base));
      rts[(i << 1) + 1] = C(cos(angle_i), sin(angle_i));
    }
    ++base;
  }
}

void fft(vector<C> &a, int n) {
  assert((n & (n - 1)) == 0);
  int zeros = __builtin_ctz(n);
  ensure_base(zeros);
  int shift = base - zeros;
  for (int i = 0; i < n; i++) {
    if (i < (rev[i] >> shift)) {
      swap(a[i], a[rev[i] >> shift]);
    }
  }
  for (int k = 1; k < n; k <<= 1) {
    for (int i = 0; i < n; i += 2 * k) {
      for (int j = 0; j < k; j++) {
        C z = a[i + j + k] * rts[j + k];
        a[i + j + k] = a[i + j] - z;
        a[i + j] = a[i + j] + z;
      }
    }
  }
}

vector<int64_t> multiply(const vector<int> &a, const vector<int> &b) {
  int need = (int)a.size() + (int)b.size() - 1;
  int nbase = 1;
  while ((1 << nbase) < need)
    nbase++;
  ensure_base(nbase);
  int sz = 1 << nbase;
  vector<C> fa(sz);
  for (int i = 0; i < sz; i++) {
    int x = (i < (int)a.size() ? a[i] : 0);
    int y = (i < (int)b.size() ? b[i] : 0);
    fa[i] = C(x, y);
  }
  fft(fa, sz);
  C r(0, -0.25 / (sz >> 1)), s(0, 1), t(0.5, 0);
  for (int i = 0; i <= (sz >> 1); i++) {
    int j = (sz - i) & (sz - 1);
    C z = (fa[j] * fa[j] - (fa[i] * fa[i]).conj()) * r;
    fa[j] = (fa[i] * fa[i] - (fa[j] * fa[j]).conj()) * r;
    fa[i] = z;
  }
  for (int i = 0; i < (sz >> 1); i++) {
    C A0 = (fa[i] + fa[i + (sz >> 1)]) * t;
    C A1 = (fa[i] - fa[i + (sz >> 1)]) * t * rts[(sz >> 1) + i];
    fa[i] = A0 + A1 * s;
  }
  fft(fa, sz >> 1);
  vector<int64_t> ret(need);
  for (int i = 0; i < need; i++) {
    ret[i] = llround(i & 1 ? fa[i >> 1].y : fa[i >> 1].x);
  }
  return ret;
}
}; // namespace FastFourierTransform
template <typename T> struct ArbitraryModConvolution {
  using real = FastFourierTransform::real;
  using C = FastFourierTransform::C;

  ArbitraryModConvolution() = default;

  vector<T> multiply(const vector<T> &a, const vector<T> &b, int need = -1) {
    if (need == -1)
      need = a.size() + b.size() - 1;
    int nbase = 0;
    while ((1 << nbase) < need)
      nbase++;
    FastFourierTransform::ensure_base(nbase);
    int sz = 1 << nbase;
    vector<C> fa(sz);
    for (int i = 0; i < a.size(); i++) {
      fa[i] = C(a[i].x & ((1 << 15) - 1), a[i].x >> 15);
    }
    fft(fa, sz);
    vector<C> fb(sz);
    if (a == b) {
      fb = fa;
    } else {
      for (int i = 0; i < b.size(); i++) {
        fb[i] = C(b[i].x & ((1 << 15) - 1), b[i].x >> 15);
      }
      fft(fb, sz);
    }
    real ratio = 0.25 / sz;
    C r2(0, -1), r3(ratio, 0), r4(0, -ratio), r5(0, 1);
    for (int i = 0; i <= (sz >> 1); i++) {
      int j = (sz - i) & (sz - 1);
      C a1 = (fa[i] + fa[j].conj());
      C a2 = (fa[i] - fa[j].conj()) * r2;
      C b1 = (fb[i] + fb[j].conj()) * r3;
      C b2 = (fb[i] - fb[j].conj()) * r4;
      if (i != j) {
        C c1 = (fa[j] + fa[i].conj());
        C c2 = (fa[j] - fa[i].conj()) * r2;
        C d1 = (fb[j] + fb[i].conj()) * r3;
        C d2 = (fb[j] - fb[i].conj()) * r4;
        fa[i] = c1 * d1 + c2 * d2 * r5;
        fb[i] = c1 * d2 + c2 * d1;
      }
      fa[j] = a1 * b1 + a2 * b2 * r5;
      fb[j] = a1 * b2 + a2 * b1;
    }
    fft(fa, sz);
    fft(fb, sz);
    vector<T> ret(need);
    for (int i = 0; i < need; i++) {
      int64_t aa = llround(fa[i].x);
      int64_t bb = llround(fb[i].x);
      int64_t cc = llround(fa[i].y);
      aa = T(aa).x, bb = T(bb).x, cc = T(cc).x;
      ret[i] = aa + (bb << 15) + (cc << 30);
    }
    return ret;
  }
};
vector<ll> inv, FactorialInv, Factorial;
ll beki(ll a, ll b) {
  ll ret = 1 % mod;
  a %= mod;
  while (b) {
    if (b & 1LL)
      ret = ret * a % mod;
    a = a * a % mod;
    b >>= 1;
  }
  return ret;
}
void init_combination(ll MAX) {
  Factorial.resize(MAX + 1);
  FactorialInv.resize(MAX + 1);
  inv.resize(MAX + 1);
  Factorial[0] = 1;
  inv[0] = 1;
  for (int i = 1; i <= MAX; i++) {
    Factorial[i] = Factorial[i - 1] * i % mod;
  }
  FactorialInv[MAX] = beki(Factorial[MAX], mod - 2);
  for (ll i = MAX - 1; i >= 0; i--) {
    FactorialInv[i] = FactorialInv[i + 1] * (i + 1) % mod;
  }
  for (int i = 1; i <= MAX; i++) {
    inv[i] = FactorialInv[i] * Factorial[i - 1] % mod;
  }
}
ll combination(ll a, ll b) {
  if ((a == b) || (b == 0)) {
    return 1;
  }
  if (a < b)
    return 0;
  if (b < 0)
    return 0;
  ll ans = Factorial[a] * FactorialInv[b] % mod;
  ans = ans * FactorialInv[a - b] % mod;
  return ans;
}
ll N, M, K;
modint f(ll M, ll K) {
  modint ret = 0;
  vector<modint> C;
  vector<modint> A(M + 1), B(K + 1);
  for (int i = 0; i <= M; i++) {
    A[i] = FactorialInv[i];
  }
  for (int i = 0; i <= K; i++) {
    B[i] = FactorialInv[i];
  }
  ArbitraryModConvolution<modint> NTT;
  C = NTT.multiply(A, B);
  for (int s = 0; s <= M + K; s++) {
    modint tmp1 = Factorial[N + s];
    tmp1 *= C[s];
    ret += tmp1 * beki(beki(3, mod - 2), s);
    // cerr << s << " " << tmp1 << " " << tmp2 << endl;
  }
  return ret;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  init_combination(1e6);
  cin >> N >> M >> K;
  modint ans = 0;
  /*
  for(int s = 0; s <= M + K; s++) {
      modint tmp1 = Factorial[N+s] * FactorialInv[N];
      tmp1 *= C[s];
      modint tmp2 = 0;
      if(s) {
          tmp2 = Factorial[N+s-1] * FactorialInv[N];
          tmp2 *= C[s-1];
          tmp2 *= 2;
      }
      modint tmp = (tmp1 - tmp2);
      ans += tmp * beki(3, M + K - s);
      cerr << s << " " << tmp1 << " " << tmp2 << endl;
  }
  */
  ans += f(M, K);
  cerr << ans << endl;
  ans -= f(M - 1, K) * beki(3, mod - 2);
  cerr << ans << endl;
  ans -= f(M, K - 1) * beki(3, mod - 2);
  cerr << ans << endl;
  ans *= FactorialInv[N];
  ans *= beki(3, M + K);
  cout << ans << endl;
  return 0;
}