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

#include <bits/stdc++.h>

using namespace std;
int n, m, r;

typedef long long ll;
class LINT {
  static const ll BASE = 100000000LL;
  vector<ll> vl;
  bool sign;

public:
  LINT() { sign = true; }
  LINT(ll x) {
    if (x < 0) {
      sign = false;
      x *= -1;
    } else
      sign = true;
    while (x) {
      vl.push_back(x % BASE);
      x /= BASE;
    }
  }
  LINT(string &x) {
    sign = x[0] == '-' ? false : true;
    ll dc = BASE;
    for (int i = x.size() - 1; i >= 0; --i) {
      if (dc == BASE) {
        vl.push_back(0);
        dc = 1;
      }
      if (x[i] == '-')
        continue;
      else {
        vl.back() += (x[i] - '0') * dc;
        dc *= 10;
      }
    }
  }
  string getlint() {
    stringstream ss;
    if (!sign)
      ss << '-';
    for (int i = vl.size() - 1; i >= 0; --i) {
      ss << vl[i];
      ss << setw(8) << setfill('0');
    }
    return ss.str();
  }
  LINT operator+(LINT &x) {
    if (sign && !x.sign) {
      LINT t = x;
      t.sign = !t.sign;
      return *this - t;
    } else if (!sign && x.sign) {
      LINT t = *this;
      t.sign = !t.sign;
      return x - t;
    }
    LINT ret;
    ret.sign = sign;
    ll carry = 0;
    int i = 0;
    while (i < vl.size() || i < x.vl.size() || carry > 0) {
      if (i < vl.size())
        carry += vl[i];
      if (i < x.vl.size())
        carry += x.vl[i];
      ret.vl.push_back(carry % BASE);
      carry /= BASE;
      ++i;
    }
    return ret;
  }
  LINT operator-(LINT &x) {
    if (!x.sign) {
      LINT t = x;
      t.sign = !t.sign;
      return *this + t;
    }
    LINT ret;
    ll carry = 0;
    int i = 0;
    while (i < vl.size() || i < x.vl.size()) {
      if (i < vl.size())
        carry += vl[i];
      if (i < x.vl.size())
        carry -= x.vl[i];
      if (carry < 0) {
        ret.vl.push_back(carry + BASE);
        carry = -1;
      } else {
        ret.vl.push_back(carry);
        carry = 0;
      }
      ++i;
    }
    if (carry == -1) {
      ret.sign = !ret.sign;
      for (int j = 0; j < ret.vl.size(); ++j)
        ret.vl[j] = BASE - ret.vl[j] - (j != 0);
    }
    while (ret.vl.size() > 1 && ret.vl.back() == 0)
      ret.vl.pop_back();
    return ret;
  }
  LINT operator*(LINT &x) {
    LINT ret;
    if (vl.size() == 0 || x.vl.size() == 0)
      return ret;
    ret.sign = !(sign ^ x.sign);
    ret.vl.assign(vl.size() + x.vl.size(), 0);
    for (int i = 0; i < vl.size(); ++i) {
      for (int j = 0; j < x.vl.size(); ++j) {
        ret.vl[i + j] += vl[i] * x.vl[j];
        ret.vl[i + j + 1] += ret.vl[i + j] / BASE;
        ret.vl[i + j] %= BASE;
      }
    }
    while (ret.vl.size() > 0 && ret.vl.back() == 0)
      ret.vl.pop_back();
    return ret;
  }
  LINT operator/(LINT &x) {
    LINT ret, zero;
    if (vl.size() < x.vl.size())
      return ret;
    LINT F(BASE / (x.vl[x.vl.size() - 1] + 1));
    LINT t = *this * F, tx = x * F;
    ret.vl.assign(t.vl.size() - tx.vl.size() + 1, 0);
    for (int i = ret.vl.size() - 1, j = t.vl.size() - 1; i >= 0; --i, --j) {
      ret.vl[i] = (j + 1 < t.vl.size() ? t.vl[j + 1] : 0) * BASE + t.vl[j];
      ret.vl[i] /= tx.vl[tx.vl.size() - 1];
      LINT tt;
      tt.vl.assign(i + tx.vl.size(), 0);
      for (int k = 0; k < tx.vl.size(); ++k)
        tt.vl[i + k] = ret.vl[i] * tx.vl[k];
      tt = tt + zero;
      while (t < tt) {
        --ret.vl[i];
        for (int k = 0; k < tx.vl.size(); ++k)
          tt.vl[i + k] -= tx.vl[k];
        tt = tt - zero;
      }
      t = t - tt;
    }
    ret = ret - zero;
    ret.sign = !(sign ^ x.sign);
    while (ret.vl.size() > 0 && ret.vl.back() == 0)
      ret.vl.pop_back();
    return ret;
    // return tt/F;
  }
  bool operator<(LINT &x) {
    if (sign ^ x.sign)
      return x.sign;
    if (vl.size() != x.vl.size())
      return !(sign ^ (vl.size() < x.vl.size()));
    for (int i = vl.size() - 1; i >= 0; --i) {
      if (vl[i] != x.vl[i])
        return !(sign ^ (vl[i] < x.vl[i]));
    }
    return false;
  }
};

string combination(int n, int k) {
  if (n - k < k)
    k = n - k;
  vector<int> v(k);
  for (int i = 0; i < k; ++i)
    v[i] = n - i;
  for (int i = 1; i <= k; ++i) {
    int t = i;
    for (int j = 0; j < k; ++j) {
      int s = __gcd(t, v[j]);
      v[j] /= s;
      t /= s;
    }
  }
  LINT ret(1);
  for (int i = 0; i < k; ++i) {
    LINT t = LINT(v[i]);
    ret = ret * t;
  }
  return ret.getlint();
}

int main() {
  string ans;
  cin >> n >> m >> r;
  if (r < m * n)
    ans = '0';
  else {
    r -= m * n;
    ans = combination(r + n - 1, r);
  }
  cout << ans << endl;
  return 0;
}

Error: TLE

Fixed submission:

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

using namespace std;
int n, m, r;

string mlt_len_sum(string s, string t) {
  int sz = max(s.size(), t.size());
  if (s.size() >= t.size()) {
    string u(s.size() - t.size(), '0');
    t = u + t;
  } else {
    string u(t.size() - s.size(), '0');
    s = u + s;
  }
  int f = 0;
  string sum(sz, '0');
  for (int i = sz - 1; i >= 0; --i) {
    int d = s[i] - '0' + t[i] - '0' + f;
    f = d / 10;
    d %= 10;
    sum[i] = d + '0';
  }
  if (f == 1)
    sum = '1' + sum;
  return sum;
}

void combination(vector<vector<string>> &v) {
  v[1][0] = '1';
  for (int i = 0; i < v[0].size(); ++i) {
    v[i % 2][i] = '1';
  }
  for (int i = 1; i < v[0].size(); ++i) {
    for (int j = 1; j < i; ++j) {
      if (i > r && (j < i - r || j > r))
        continue;
      v[i % 2][j] = mlt_len_sum(v[(i - 1) % 2][j - 1], v[(i - 1) % 2][j]);
    }
  }
}

int main() {
  string ans;
  cin >> n >> m >> r;
  if (r < m * n)
    ans = '0';
  else {
    r -= m * n;
    vector<vector<string>> v(2, vector<string>(r + n));
    combination(v);
    ans = v[(r + n - 1) % 2][r];
  }
  cout << ans << endl;
  return 0;
}