Problem p00514 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cassert>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <string>

using namespace std;

typedef long long Int;
const Int B = 10000000000; // base (power of 10)
const int BW = 10;         // log B
const int MAXDIGIT = 4000; // it can represent BW*MAXDIGIT digits (in base 10)
struct BigNum {
  Int digit[MAXDIGIT];
  int size;
  BigNum(int size, Int a) : size(size) {
    memset(digit, 0, sizeof(digit));
    digit[0] = a;
  }
  BigNum(Int a);
  BigNum(const string &s);
};

const BigNum ZERO(1, 0), ONE(1, 1);

// Comparators
inline bool operator<(const BigNum &x, const BigNum &y) {
  if (x.size != y.size)
    return x.size < y.size;
  for (int i = x.size - 1; i >= 0; --i)
    if (x.digit[i] != y.digit[i])
      return x.digit[i] < y.digit[i];
  return false;
}
inline bool operator>(const BigNum &x, const BigNum &y) { return y < x; }
inline bool operator<=(const BigNum &x, const BigNum &y) { return !(y < x); }
inline bool operator>=(const BigNum &x, const BigNum &y) { return !(x < y); }
inline bool operator!=(const BigNum &x, const BigNum &y) {
  return x < y || y < x;
}
inline bool operator==(const BigNum &x, const BigNum &y) {
  return !(x < y) && !(y < x);
}

// Utilities
inline BigNum normal(BigNum x) {
  Int c = 0;
  for (int i = 0; i < x.size; ++i) {
    while (x.digit[i] < 0)
      x.digit[i + 1] -= 1, x.digit[i] += B;
    Int a = x.digit[i] + c;
    x.digit[i] = a % B;
    c = a / B;
  }
  for (; c > 0; c /= B)
    x.digit[x.size++] = c % B;
  while (x.size > 1 && x.digit[x.size - 1] == 0)
    --x.size;
  return x;
}
BigNum::BigNum(Int a) { *this = normal(BigNum(1, a)); }
BigNum::BigNum(const string &s) {
  BigNum x(1, 0);
  int i = s.size() % BW;
  if (i > 0)
    i -= BW;
  for (; i < (int)s.size(); i += BW) {
    Int a = 0;
    for (int j = 0; j < BW; ++j)
      a = 10 * a + (i + j >= 0 ? s[i + j] - '0' : 0);
    x.digit[x.size++] = a;
  }
  reverse(x.digit, x.digit + x.size);
  *this = normal(x);
}

// Input/Output
ostream &operator<<(ostream &os, const BigNum &x) {
  os << x.digit[x.size - 1];
  for (int i = x.size - 2; i >= 0; --i)
    os << setw(BW) << setfill('0') << x.digit[i];
  return os;
}
istream &operator>>(istream &is, BigNum &x) {
  string s;
  is >> s;
  x = BigNum(s);
  return is;
}

// Basic Operations
inline BigNum operator+(BigNum x, const BigNum &y) {
  if (x.size < y.size)
    x.size = y.size;
  for (int i = 0; i < y.size; ++i)
    x.digit[i] += y.digit[i];
  return normal(x);
}
inline BigNum operator-(BigNum x, const BigNum &y) {
  assert(x >= y);
  for (int i = 0; i < y.size; ++i)
    x.digit[i] -= y.digit[i];
  return normal(x);
}
inline BigNum operator*(BigNum x, const BigNum &y) {
  BigNum z(x.size + y.size, 0);
  for (int i = 0; i < x.size; ++i)
    for (int j = 0; j < y.size; ++j)
      z.digit[i + j] += x.digit[i] * y.digit[j];
  return normal(z);
}
inline BigNum operator*(BigNum x, Int a) {
  for (int i = 0; i < x.size; ++i)
    x.digit[i] *= a;
  return normal(x);
}
inline pair<BigNum, Int> divmod(BigNum x, Int a) {
  Int c = 0, t;
  for (int i = x.size - 1; i >= 0; --i) {
    t = B * c + x.digit[i];
    x.digit[i] = t / a;
    c = t % a;
  }
  return pair<BigNum, Int>(normal(x), c);
}
inline BigNum operator/(BigNum x, Int a) { return divmod(x, a).first; }
inline Int operator%(BigNum x, Int a) { return divmod(x, a).second; }
inline pair<BigNum, BigNum> divmod(BigNum x, BigNum y) {
  if (x.size < y.size)
    return pair<BigNum, BigNum>(ZERO, x);
  int F = B / (y.digit[y.size - 1] + 1); // multiplying good-factor
  x = x * F;
  y = y * F;
  BigNum z(x.size - y.size + 1, 0);
  for (int k = z.size - 1, i = x.size - 1; k >= 0; --k, --i) {
    z.digit[k] = (i + 1 < x.size ? x.digit[i + 1] : 0) * B + x.digit[i];
    z.digit[k] /= y.digit[y.size - 1];
    BigNum t(k + y.size, 0);
    for (int m = 0; m < y.size; ++m)
      t.digit[k + m] = z.digit[k] * y.digit[m];
    t = normal(t);
    while (x < t) {
      z.digit[k] -= 1;
      for (int m = 0; m < y.size; ++m)
        t.digit[k + m] -= y.digit[m];
      t = normal(t);
    }
    x = x - t;
  }
  return pair<BigNum, BigNum>(normal(z), x / F);
}
inline BigNum operator/(BigNum x, BigNum y) { return divmod(x, y).first; }
inline BigNum operator%(BigNum x, BigNum y) { return divmod(x, y).second; }

// Advanced Operations
inline BigNum shift(BigNum x, int k) {
  if (x.size == 1 && x.digit[0] == 0)
    return x;
  x.size += k;
  for (int i = x.size - 1; i >= k; --i)
    x.digit[i] = x.digit[i - k];
  for (int i = k - 1; i >= 0; --i)
    x.digit[i] = 0;
  return x;
}
inline BigNum sqrt(const BigNum &x) { // verified UVA 10023
  const BigNum _20(2 * B);
  BigNum odd = ZERO;
  BigNum rem(2, 0);
  BigNum ans = ZERO;
  for (int i = 2 * ((x.size - 1) / 2); i >= 0; i -= 2) {
    int group = (i + 1 < x.size ? x.digit[i + 1] : 0) * B + x.digit[i];
    odd = _20 * ans + ONE;
    rem = shift(rem, 2) + BigNum(group);
    int count = 0;
    while (rem >= odd) {
      count = count + 1;
      rem = rem - odd;
      odd.digit[0] += 2;
      odd = normal(odd);
    }
    ans = shift(ans, 1) + BigNum(count);
  }
  return ans;
}

int main() {
  int n, m, r;
  while (cin >> n >> m >> r) {
    int x = r - n * m + n - 1;
    int y = r - m * n;
    BigNum ans(1, 0);
    if (y < 0 || x < 0)
      ans = ZERO;
    else {
      ans = BigNum(1);
      for (int i = 1; i <= y; i++) {
        ans = ans * (x - i + 1);
        ans = ans / i;
      }
    }
    cout << ans << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

using int_t = int;
constexpr int_t BASE = 1000000000, LEN = 9;
class bigint {
private:
  bool negative;
  std::vector<int_t> a;
  bigint &normalize();

public:
  bigint(int_t x = 0);
  bigint(const std::string &s);
  bigint &operator=(const bigint &x);
  bigint &operator=(int_t x);
  bigint &operator=(const std::string &s);
  bool operator<(const bigint &x) const;
  bool operator>(const bigint &x) const;
  bool operator<=(const bigint &x) const;
  bool operator>=(const bigint &x) const;
  bool operator!=(const bigint &x) const;
  bool operator==(const bigint &x) const;
  bigint operator-() const;
  bigint &operator+=(const bigint &x);
  bigint &operator-=(const bigint &x);
  bigint &operator*=(const bigint &x);
  bigint &operator/=(const bigint &x);
  bigint &operator%=(const bigint &x);
  const bigint operator+(const bigint &x) const;
  const bigint operator-(const bigint &x) const;
  const bigint operator*(const bigint &x) const;
  const bigint operator/(const bigint &x) const;
  const bigint operator%(const bigint &x) const;
  friend std::pair<bigint, bigint> divmod(const bigint &lhs, const bigint &rhs);
  friend std::istream &operator>>(std::ostream &is, bigint &x); //??????????£?
  friend std::ostream &operator<<(std::ostream &os, const bigint &x);
  friend const bigint abs(bigint x);
};
inline bigint &bigint::normalize() {
  int i = a.size() - 1;
  while (i >= 0 && a[i] == 0)
    --i;
  a.resize(i + 1);
  if (a.size() == 0)
    negative = false;
  return *this;
}
inline bigint::bigint(int_t x) : negative(x < 0) {
  x = abs(x);
  for (; x > 0; x /= BASE)
    a.push_back(x % BASE);
}
inline bigint::bigint(const std::string &s) : negative(false) {
  int p = 0;
  if (s[p] == '-') {
    ++p;
    negative = true;
  } else if (s[p] == '+') {
    ++p;
  }
  int_t v = BASE;
  for (int i = s.size() - 1; i >= p; --i, v *= 10) {
    int x = s[i] - '0';
    if (x < 0 || 9 < x) {
      std::cerr << "error: parse error:" << s << std::endl;
      exit(1);
    }
    if (v == BASE) {
      v = 1;
      a.push_back(x);
    } else
      a.back() += (x)*v;
  }
  normalize();
}
inline bigint &bigint::operator=(const bigint &x) {
  negative = x.negative;
  a = x.a;
  return *this;
}
inline bigint &bigint::operator=(int_t x) { return *this = bigint(x); }
inline bigint &bigint::operator=(const std::string &s) {
  return *this = bigint(s);
}
inline bool bigint::operator<(const bigint &x) const {
  if (negative != x.negative)
    return negative > x.negative;
  if (a.size() != x.a.size())
    return (a.size() < x.a.size()) ^ negative;
  for (int i = a.size() - 1; i >= 0; --i)
    if (a[i] != x.a[i])
      return (a[i] < x.a[i]) ^ negative;
  return false;
}
inline bool bigint::operator>(const bigint &x) const { return x < (*this); }
inline bool bigint::operator<=(const bigint &x) const { return !(x < (*this)); }
inline bool bigint::operator>=(const bigint &x) const { return !((*this) < x); }
inline bool bigint::operator!=(const bigint &x) const {
  return (*this) < x || x < (*this);
}
inline bool bigint::operator==(const bigint &x) const {
  return !((*this) < x || x < (*this));
}
inline bigint bigint::operator-() const {
  bigint ret(*this);
  if (a.size())
    ret.negative = !ret.negative;
  return ret;
}
inline bigint &bigint::operator+=(const bigint &x) {
  if (negative != x.negative)
    return *this -= -x;
  if (a.size() < x.a.size())
    a.resize(x.a.size());
  int_t tmp = 0;
  for (int i = 0; i < (int)a.size(); ++i) {
    a[i] += (i < (int)x.a.size() ? x.a[i] : 0) + tmp;
    tmp = a[i] / BASE;
    a[i] %= BASE;
  }
  if (tmp)
    a.push_back(1);
  return *this;
}
inline bigint &bigint::operator-=(const bigint &x) {
  if (negative != x.negative)
    return *this += -x;
  std::vector<int_t> b(x.a);
  if ((*this < x) ^ negative) {
    a.swap(b);
    negative = !negative;
  }
  int_t tmp = 0;
  for (int i = 0; i < (int)a.size(); ++i) {
    a[i] += BASE - (i < (int)b.size() ? b[i] : 0) + tmp;
    tmp = a[i] / BASE - 1;
    a[i] %= BASE;
  }
  return this->normalize();
}
inline bigint &bigint::operator*=(const bigint &x) {
  negative ^= x.negative;
  std::vector<int_t> c(a.size() * x.a.size() + 1);
  for (int i = 0; i < (int)a.size(); ++i) {
    long long tmp = 0;
    for (int j = 0; j < (int)x.a.size(); ++j) {
      long long v = (long long)a[i] * x.a[j] + c[i + j] + tmp;
      tmp = v / BASE;
      c[i + j] = (int_t)(v % BASE);
    }
    if (tmp)
      c[i + x.a.size()] += (int_t)tmp;
  }
  a.swap(c);
  return this->normalize();
}
inline bigint &bigint::operator/=(const bigint &x) {
  return *this = divmod(*this, x).first;
}
inline bigint &bigint::operator%=(const bigint &x) {
  return *this = divmod(*this, x).second;
}
inline const bigint bigint::operator+(const bigint &x) const {
  bigint res(*this);
  return res += x;
}
inline const bigint bigint::operator-(const bigint &x) const {
  bigint res(*this);
  return res -= x;
}
inline const bigint bigint::operator*(const bigint &x) const {
  bigint res(*this);
  return res *= x;
}
inline const bigint bigint::operator/(const bigint &x) const {
  bigint res(*this);
  return res /= x;
}
inline const bigint bigint::operator%(const bigint &x) const {
  bigint res(*this);
  return res %= x;
}
inline std::pair<bigint, bigint> divmod(const bigint &lhs, const bigint &rhs) {
  if (!rhs.a.size()) {
    std::cerr << "error: division by zero" << std::endl;
    exit(1);
  }
  bigint x(abs(rhs)), q, r;
  for (int i = lhs.a.size() - 1; i >= 0; --i) {
    r = r * BASE + lhs.a[i];
    int_t head = 0, tail = BASE;
    if (r >= x) {
      while (head + 1 < tail) {
        int_t mid = (head + tail) / 2;
        if (x * bigint(mid) > r)
          tail = mid;
        else
          head = mid;
      }
      r -= x * head;
    }
    q.a.push_back(head);
  }
  std::reverse(q.a.begin(), q.a.end());
  bool neg = lhs.negative ^ lhs.negative;
  q.negative = neg;
  r.negative = neg;
  return std::make_pair(q.normalize(), r.normalize());
}
inline std::istream &operator>>(std::istream &is, bigint &x) {
  std::string tmp;
  is >> tmp;
  x = bigint(tmp);
  return is;
}
inline std::ostream &operator<<(std::ostream &os, const bigint &x) {
  if (x.negative)
    os << '-';
  if (!x.a.size())
    os << 0;
  else
    os << x.a.back();
  for (int i = x.a.size() - 2; i >= 0; --i) {
    os.width(LEN);
    os.fill('0');
    os << x.a[i];
  }
  return os;
}
inline const bigint abs(bigint x) {
  x.negative = false;
  return x;
}

using namespace std;

int main() {
  int n, m, r;
  while (cin >> n >> m >> r) {
    int x = r - n * m + n - 1;
    int y = r - m * n;
    bigint ans;
    if (y < 0 || x < 0) {
      ans = 0;
    } else {
      ans = 1;
      for (int i = 1; i <= y; i = i + 1) {
        ans = ans * (x - i + 1);
        ans = ans / i;
      }
    }
    cout << ans << endl;
  }
}