Problem p04051 (C++)

Buggy submission (status: Time Limit Exceeded):
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

// template
#define rep(i, a, b) for (int i = (a); i < (b); i++)
#define rrep(i, a, b) for (int i = (a); i > (b); i--)
#define ALL(v) (v).begin(), (v).end()
typedef long long int ll;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;
const double eps = 1e-12;
string to_str(ll x) {
  string res;
  while (x)
    res += ('0' + (x % 10)), x /= 10;
  reverse(ALL(res));
  return res;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
// template end

template <unsigned mod> struct Mint {
  int val;
  int inv() const {
    int tmp, a = val, b = mod, x = 1, y = 0;
    while (b)
      tmp = a / b, a -= tmp * b, swap(a, b), x -= tmp * y, swap(x, y);
    if (x < 0)
      x += mod;
    return x;
  }
  Mint() : val(0) {}
  Mint(ll x) : val(x >= 0 ? x % mod : mod + (x % mod)) {}
  Mint pow(ll t) {
    Mint res = 1, b = *this;
    while (t) {
      if (t & 1)
        res *= b;
      b *= b;
      t >>= 1;
    }
    return res;
  }
  Mint &operator+=(const Mint &x) {
    if ((val += x.val) >= mod)
      val -= mod;
    return *this;
  }
  Mint &operator-=(const Mint &x) {
    if ((val += mod - x.val) >= mod)
      val -= mod;
    return *this;
  }
  Mint &operator*=(const Mint &x) {
    val = (ll)val * x.val % mod;
    return *this;
  }
  Mint &operator/=(const Mint &x) {
    val = (ll)val * x.inv() % mod;
    return *this;
  }
  Mint operator+(const Mint &x) const { return Mint(*this) += x; }
  Mint operator-(const Mint &x) const { return Mint(*this) -= x; }
  Mint operator*(const Mint &x) const { return Mint(*this) *= x; }
  Mint operator/(const Mint &x) const { return Mint(*this) /= x; }
  bool operator==(const Mint &x) const { return val == x.val; }
  bool operator!=(const Mint &x) const { return val != x.val; }
};
using mint = Mint<1000000007>;
struct factorial {
  vector<mint> Fact, Finv;

public:
  factorial(int maxx) {
    Fact.resize(maxx + 1), Finv.resize(maxx + 1);
    Fact[0] = mint(1);
    rep(i, 0, maxx) Fact[i + 1] = Fact[i] * (i + 1);
    Finv[maxx] = mint(1) / Fact[maxx];
    rrep(i, maxx, 0) Finv[i - 1] = Finv[i] * i;
  }
  mint fact(int n, bool inv = 0) {
    if (inv)
      return Finv[n];
    else
      return Fact[n];
  }
  mint nPr(int n, int r) {
    if (n < 0 || n < r || r < 0)
      return mint(0);
    else
      return Fact[n] * Finv[n - r];
  }
  mint nCr(int n, int r) {
    if (n < 0 || n < r || r < 0)
      return mint(0);
    else
      return Fact[n] * Finv[r] * Finv[n - r];
  }
};

struct C {
  float x, y;
  C(double _x = 0, double _y = 0) : x(_x), y(_y) {}
  C operator~() const { return {x, -y}; }
  C operator+(const C &c) const { return {x + c.x, y + c.y}; }
  C operator-(const C &c) const { return {x - c.x, y - c.y}; }
  C operator*(const C &c) const {
    return {x * c.x - y * c.y, x * c.y + y * c.x};
  }
};
vector<C> rt;
void init(int lg = 20) {
  rt.resize(1 << lg, 1);
  rep(k, 1, lg) {
    int d = 1 << k;
    rep(i, 0, d) {
      if (i & 1)
        rt[d + i - 1] = C(cos(2 * M_PI * i / d), sin(2 * M_PI * i / d));
      else
        rt[d + i - 1] = rt[(d + i) / 2 - 1];
    }
  }
}
void fft(vector<C> &a, bool inv = 0, int n = -1) {
  if (n == -1)
    n = a.size();
  if (inv) {
    for (int i = 1; i < n; i <<= 1) {
      for (int j = 0; j < n; j += i * 2) {
        rep(k, 0, i) {
          a[i + j + k] = a[i + j + k] * ~rt[i * 2 - 1 + k];
          const C tmp = a[j + k] - a[i + j + k];
          a[j + k] = a[j + k] + a[i + j + k];
          a[i + j + k] = tmp;
        }
      }
    }
    // rep(i,0,n)a[i].x/=n,a[i].y/=n;
  } else {
    for (int i = n >> 1; i; i >>= 1) {
      for (int j = 0; j < n; j += i * 2) {
        rep(k, 0, i) {
          const C tmp = a[j + k] - a[i + j + k];
          a[j + k] = a[j + k] + a[i + j + k];
          a[i + j + k] = tmp * rt[i * 2 - 1 + k];
        }
      }
    }
  }
} // need to initialize

int sz = 1 << 12;
mint ans;
factorial fact(8020);
vector<vector<C>> buf(sz, vector<C>(sz));
void fft2d(bool inv = 0) {
  rep(i, 0, sz) fft(buf[i], inv);
  rep(i, 0, sz) rep(j, 0, i) swap(buf[i][j], buf[j][i]);
  rep(i, 0, sz) fft(buf[i], inv);
  if (inv)
    rep(i, 0, sz) rep(j, 0, sz) buf[i][j].x /= sz * sz;
}

map<pair<int, int>, int> mp;
void sub() {
  for (auto p1 : mp)
    for (auto p2 : mp) {
      int a = p1.first.first, b = p1.first.second;
      int c = p2.first.first, d = p2.first.second;
      ans += fact.nCr(a + b + c + d, a + c) * p1.second * p2.second;
    }
  ans /= 2;
  printf("%d\n", ans.val);
  exit(0);
}

int main() {
  init(15);
  int n;
  scanf("%d", &n);
  rep(i, 0, n) {
    int h, w;
    scanf("%d%d", &h, &w);
    mp[{h, w}]++;
    buf[h][w].x += 1.0;
    ans -= fact.nCr((h + w) * 2, h * 2);
  }
  if (mp.size() <= 10000)
    sub();
  fft2d();
  rep(i, 0, sz) rep(j, 0, sz) buf[i][j] = buf[i][j] * buf[i][j];
  fft2d(1);
  rep(i, 0, sz) rep(j, 0, sz) {
    mint tmp((ll)(buf[i][j].x + 0.5));
    ans += fact.nCr(i + j, i) * tmp;
  }
  ans /= 2;
  printf("%d\n", ans.val);
  return 0;
}

Fixed submission:
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;

// template
#define rep(i, a, b) for (int i = (a); i < (b); i++)
#define rrep(i, a, b) for (int i = (a); i > (b); i--)
#define ALL(v) (v).begin(), (v).end()
typedef long long int ll;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;
const double eps = 1e-12;
string to_str(ll x) {
  string res;
  while (x)
    res += ('0' + (x % 10)), x /= 10;
  reverse(ALL(res));
  return res;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
// template end

template <unsigned mod> struct Mint {
  int val;
  int inv() const {
    int tmp, a = val, b = mod, x = 1, y = 0;
    while (b)
      tmp = a / b, a -= tmp * b, swap(a, b), x -= tmp * y, swap(x, y);
    if (x < 0)
      x += mod;
    return x;
  }
  Mint() : val(0) {}
  Mint(ll x) : val(x >= 0 ? x % mod : mod + (x % mod)) {}
  Mint pow(ll t) {
    Mint res = 1, b = *this;
    while (t) {
      if (t & 1)
        res *= b;
      b *= b;
      t >>= 1;
    }
    return res;
  }
  Mint &operator+=(const Mint &x) {
    if ((val += x.val) >= mod)
      val -= mod;
    return *this;
  }
  Mint &operator-=(const Mint &x) {
    if ((val += mod - x.val) >= mod)
      val -= mod;
    return *this;
  }
  Mint &operator*=(const Mint &x) {
    val = (ll)val * x.val % mod;
    return *this;
  }
  Mint &operator/=(const Mint &x) {
    val = (ll)val * x.inv() % mod;
    return *this;
  }
  Mint operator+(const Mint &x) const { return Mint(*this) += x; }
  Mint operator-(const Mint &x) const { return Mint(*this) -= x; }
  Mint operator*(const Mint &x) const { return Mint(*this) *= x; }
  Mint operator/(const Mint &x) const { return Mint(*this) /= x; }
  bool operator==(const Mint &x) const { return val == x.val; }
  bool operator!=(const Mint &x) const { return val != x.val; }
};
using mint = Mint<1000000007>;
struct factorial {
  vector<mint> Fact, Finv;

public:
  factorial(int maxx) {
    Fact.resize(maxx + 1), Finv.resize(maxx + 1);
    Fact[0] = mint(1);
    rep(i, 0, maxx) Fact[i + 1] = Fact[i] * (i + 1);
    Finv[maxx] = mint(1) / Fact[maxx];
    rrep(i, maxx, 0) Finv[i - 1] = Finv[i] * i;
  }
  mint fact(int n, bool inv = 0) {
    if (inv)
      return Finv[n];
    else
      return Fact[n];
  }
  mint nPr(int n, int r) {
    if (n < 0 || n < r || r < 0)
      return mint(0);
    else
      return Fact[n] * Finv[n - r];
  }
  mint nCr(int n, int r) {
    if (n < 0 || n < r || r < 0)
      return mint(0);
    else
      return Fact[n] * Finv[r] * Finv[n - r];
  }
};

struct C {
  float x, y;
  C(double _x = 0, double _y = 0) : x(_x), y(_y) {}
  C operator~() const { return {x, -y}; }
  C operator+(const C &c) const { return {x + c.x, y + c.y}; }
  C operator-(const C &c) const { return {x - c.x, y - c.y}; }
  C operator*(const C &c) const {
    return {x * c.x - y * c.y, x * c.y + y * c.x};
  }
};
vector<C> rt;
void init(int lg = 20) {
  rt.resize(1 << lg, 1);
  rep(k, 1, lg) {
    int d = 1 << k;
    rep(i, 0, d) {
      if (i & 1)
        rt[d + i - 1] = C(cos(2 * M_PI * i / d), sin(2 * M_PI * i / d));
      else
        rt[d + i - 1] = rt[(d + i) / 2 - 1];
    }
  }
}
void fft(vector<C> &a, bool inv = 0, int n = -1) {
  if (n == -1)
    n = a.size();
  if (inv) {
    for (int i = 1; i < n; i <<= 1) {
      for (int j = 0; j < n; j += i * 2) {
        rep(k, 0, i) {
          a[i + j + k] = a[i + j + k] * ~rt[i * 2 - 1 + k];
          const C tmp = a[j + k] - a[i + j + k];
          a[j + k] = a[j + k] + a[i + j + k];
          a[i + j + k] = tmp;
        }
      }
    }
    // rep(i,0,n)a[i].x/=n,a[i].y/=n;
  } else {
    for (int i = n >> 1; i; i >>= 1) {
      for (int j = 0; j < n; j += i * 2) {
        rep(k, 0, i) {
          const C tmp = a[j + k] - a[i + j + k];
          a[j + k] = a[j + k] + a[i + j + k];
          a[i + j + k] = tmp * rt[i * 2 - 1 + k];
        }
      }
    }
  }
} // need to initialize

int sz = 1 << 12;
mint ans;
factorial fact(8020);
vector<vector<C>> buf(sz, vector<C>(sz));
void fft2d(bool inv = 0) {
  rep(i, 0, (inv ? sz : sz / 2)) fft(buf[i], inv);
  rep(i, 0, sz) rep(j, 0, i) swap(buf[i][j], buf[j][i]);
  rep(i, 0, sz) fft(buf[i], inv);
  if (inv)
    rep(i, 0, sz) rep(j, 0, sz) buf[i][j].x /= sz * sz;
}

map<pair<int, int>, int> mp;
void sub() {
  for (auto p1 : mp)
    for (auto p2 : mp) {
      int a = p1.first.first, b = p1.first.second;
      int c = p2.first.first, d = p2.first.second;
      ans += fact.nCr(a + b + c + d, a + c) * p1.second * p2.second;
    }
  ans /= 2;
  printf("%d\n", ans.val);
  exit(0);
}

int main() {
  init(15);
  int n;
  scanf("%d", &n);
  rep(i, 0, n) {
    int h, w;
    scanf("%d%d", &h, &w);
    mp[{h, w}]++;
    buf[h][w].x += 1.0;
    ans -= fact.nCr((h + w) * 2, h * 2);
  }
  if (mp.size() <= 10000)
    sub();
  fft2d();
  rep(i, 0, sz) rep(j, 0, sz) buf[i][j] = buf[i][j] * buf[i][j];
  fft2d(1);
  rep(i, 0, sz) rep(j, 0, sz) {
    mint tmp((ll)(buf[i][j].x + 0.5));
    ans += fact.nCr(i + j, i) * tmp;
  }
  ans /= 2;
  printf("%d\n", ans.val);
  return 0;
}