Problem p00514 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
static const double EPS = 1e-10;
typedef long long ll;
#define rep(i, n) for (int i = 0; i < n; i++)
#define rev(i, n) for (int i = n - 1; i >= 0; i--)
#define all(a) a.begin(), a.end()
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a)
#define SS stringstream
#define DBG1(a)                                                                \
  rep(_X, sz(a)) { printf("%d ", a[_X]); }                                     \
  puts("");
#define DBG2(a)                                                                \
  rep(_X, sz(a)) {                                                             \
    rep(_Y, sz(a[_X])) printf("%d ", a[_X][_Y]);                               \
    puts("");                                                                  \
  }
#define bitcount(b) __builtin_popcount(b)
#define EACH(i, c)                                                             \
  for (typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

#define delete(a, n) a.erase(remove(all(a), n), a.end())
template <typename T, typename S> vector<T> &operator<<(vector<T> &a, S b) {
  a.push_back(b);
  return a;
}
template <typename T> void operator>>(vector<T> &a, int b) {
  while (b--)
    if (!a.empty())
      a.pop_back();
}
bool isprime(int n) {
  if (n < 2)
    return false;
  for (int i = 2; i * i <= n; i++)
    if (n % i == 0)
      return false;
  return true;
}
ll b_pow(ll x, ll n) { return n ? b_pow(x * x, n / 2) * (n % 2 ? x : 1) : 1ll; }
string itos(int n) {
  stringstream ss;
  ss << n;
  return ss.str();
}

typedef unsigned int uint;
int in() {
  int x = 0, c;
  for (; (uint)((c = getchar()) - '0') >= 10;) {
    if (c == '-')
      return -in();
    if (!~c)
      throw ~0;
  }
  do {
    x = (x << 3) + (x << 1) + (c - '0');
  } while ((uint)((c = getchar()) - '0') < 10);
  return x;
}

vector<int> factor(int n) {
  vector<int> ret;

  int i = 2;
  while (i * i <= n) {
    if (n % i == 0)
      ret.push_back(i), n /= i, i = 2;
    else
      i++;
  }
  if (n != 1)
    ret.push_back(n);

  return ret;
}

int cnt[30001];

class bigInteger {
#define DIGITMAX (1700) // 4 * n digit
public:
  std::vector<int> value;

  bigInteger operator=(bigInteger b) {
    this->value = b.value;
    return *this;
  }
  /* O(n) */
  bigInteger operator+(bigInteger b) {
    for (int i = 0; i < DIGITMAX; i++) {
      b.value[i] += this->value[i];
      if (b.value[i] >= 10000) {
        b.value[i] -= 10000;
        b.value[i + 1]++;
      }
    }
    return b;
  }
  /* O(n) */
  bigInteger operator-(bigInteger b) {
    for (int i = 0; i < DIGITMAX; i++) {
      b.value[i] = this->value[i] - b.value[i];
      if (b.value[i] < 0) {
        b.value[i] = 10000 + b.value[i];
        b.value[i + 1]++; // b wo oome
      }
    }
    return b;
  }
  /* with bug.. O(n^2) */
  bigInteger operator*(bigInteger b) {
    bigInteger ret;
    for (int i = 0; i < DIGITMAX; i++) {
      for (int j = 0; j < DIGITMAX; j++) {
        if (i + j + 1 < DIGITMAX) {
          ret.value[i + j] += this->value[i] * b.value[j];
          ret.value[i + j + 1] += ret.value[i + j] / 10000;
          ret.value[i + j] %= 10000;
        }
      }
    }
    return ret;
  }

  string str() {
    char tmp[5];
    string retVal = "";
    for (int i = DIGITMAX - 1; i >= 0; i--) {
      sprintf(tmp, "%04d", value[i]);
      retVal += tmp;
    }
    while (retVal[0] == '0' && retVal.length() >= 2)
      retVal = retVal.substr(1);
    return retVal;
  }

  bigInteger() { this->value.resize(DIGITMAX); }
  bigInteger(string init) {
    vector<int> vi;
    for (int i = init.length() - 4; i > -4; i -= 4) {
      vi.push_back(atoi(init.substr(max(i, 0), 4 + (i < 0 ? i : 0)).c_str()));
    }
    this->value = vi;
    this->value.resize(DIGITMAX);
  }
};

int main() {
  int n = in(), m = in(), r = in();
  int R = r - n * m;
  if (R < 0) {
    cout << 0 << endl;
    return 0;
  }
  // R=2,R=3 |O|O -> (R+n-1) C (n-1)
  for (int i = 0; i < n - 1; i++) {
    vector<int> v = factor(n - 1 + R - i);
    for (int j = 0; j < v.size(); j++)
      cnt[v[j]]++;
  }
  for (int i = 0; i < n - 1; i++) {
    vector<int> v = factor(i + 1);
    for (int j = 0; j < v.size(); j++)
      cnt[v[j]]--;
  }
  bigInteger ans("1");
  for (int i = 0; i <= 30000; i++) {
    // if( cnt[i] )cout << i << " " << cnt[i] << endl;
    while (cnt[i]--)
      ans = ans * bigInteger(itos(i));
  }
  cout << ans.str() << endl;
}


Fixed submission:
#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
static const double EPS = 1e-10;
typedef long long ll;
#define rep(i, n) for (int i = 0; i < n; i++)
#define rev(i, n) for (int i = n - 1; i >= 0; i--)
#define all(a) a.begin(), a.end()
#define mp(a, b) make_pair(a, b)
#define pb(a) push_back(a)
#define SS stringstream
#define DBG1(a)                                                                \
  rep(_X, sz(a)) { printf("%d ", a[_X]); }                                     \
  puts("");
#define DBG2(a)                                                                \
  rep(_X, sz(a)) {                                                             \
    rep(_Y, sz(a[_X])) printf("%d ", a[_X][_Y]);                               \
    puts("");                                                                  \
  }
#define bitcount(b) __builtin_popcount(b)
#define EACH(i, c)                                                             \
  for (typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

#define delete(a, n) a.erase(remove(all(a), n), a.end())
template <typename T, typename S> vector<T> &operator<<(vector<T> &a, S b) {
  a.push_back(b);
  return a;
}
template <typename T> void operator>>(vector<T> &a, int b) {
  while (b--)
    if (!a.empty())
      a.pop_back();
}
bool isprime(int n) {
  if (n < 2)
    return false;
  for (int i = 2; i * i <= n; i++)
    if (n % i == 0)
      return false;
  return true;
}
ll b_pow(ll x, ll n) { return n ? b_pow(x * x, n / 2) * (n % 2 ? x : 1) : 1ll; }
string itos(int n) {
  stringstream ss;
  ss << n;
  return ss.str();
}

typedef unsigned int uint;
int in() {
  int x = 0, c;
  for (; (uint)((c = getchar()) - '0') >= 10;) {
    if (c == '-')
      return -in();
    if (!~c)
      throw ~0;
  }
  do {
    x = (x << 3) + (x << 1) + (c - '0');
  } while ((uint)((c = getchar()) - '0') < 10);
  return x;
}

vector<int> factor(int n) {
  vector<int> ret;

  int i = 2;
  while (i * i <= n) {
    if (n % i == 0)
      ret.push_back(i), n /= i, i = 2;
    else
      i++;
  }
  if (n != 1)
    ret.push_back(n);

  return ret;
}

int cnt[30001];

class bigInteger {
#define DIGITMAX (1520) // 4 * n digit
public:
  std::vector<int> value;

  bigInteger operator=(bigInteger b) {
    this->value = b.value;
    return *this;
  }
  /* O(n) */
  bigInteger operator+(bigInteger b) {
    for (int i = 0; i < DIGITMAX; i++) {
      b.value[i] += this->value[i];
      if (b.value[i] >= 10000) {
        b.value[i] -= 10000;
        b.value[i + 1]++;
      }
    }
    return b;
  }
  /* O(n) */
  bigInteger operator-(bigInteger b) {
    for (int i = 0; i < DIGITMAX; i++) {
      b.value[i] = this->value[i] - b.value[i];
      if (b.value[i] < 0) {
        b.value[i] = 10000 + b.value[i];
        b.value[i + 1]++; // b wo oome
      }
    }
    return b;
  }
  /* with bug.. O(n^2) */
  bigInteger operator*(bigInteger b) {
    bigInteger ret;
    for (int i = 0; i < DIGITMAX; i++) {
      for (int j = 0; j < DIGITMAX; j++) {
        if (i + j + 1 < DIGITMAX) {
          ret.value[i + j] += this->value[i] * b.value[j];
          ret.value[i + j + 1] += ret.value[i + j] / 10000;
          ret.value[i + j] %= 10000;
        }
      }
    }
    return ret;
  }

  string str() {
    char tmp[5];
    string retVal = "";
    for (int i = DIGITMAX - 1; i >= 0; i--) {
      sprintf(tmp, "%04d", value[i]);
      retVal += tmp;
    }
    while (retVal[0] == '0' && retVal.length() >= 2)
      retVal = retVal.substr(1);
    return retVal;
  }

  bigInteger() { this->value.resize(DIGITMAX); }
  bigInteger(string init) {
    vector<int> vi;
    for (int i = init.length() - 4; i > -4; i -= 4) {
      vi.push_back(atoi(init.substr(max(i, 0), 4 + (i < 0 ? i : 0)).c_str()));
    }
    this->value = vi;
    this->value.resize(DIGITMAX);
  }
};

int main() {
  int n = in(), m = in(), r = in();
  int R = r - n * m;
  if (R < 0) {
    cout << 0 << endl;
    return 0;
  }
  // R=2,R=3 |O|O -> (R+n-1) C (n-1)
  for (int i = 0; i < n - 1; i++) {
    vector<int> v = factor(n - 1 + R - i);
    for (int j = 0; j < v.size(); j++)
      cnt[v[j]]++;
  }
  for (int i = 0; i < n - 1; i++) {
    vector<int> v = factor(i + 1);
    for (int j = 0; j < v.size(); j++)
      cnt[v[j]]--;
  }
  bigInteger ans("1");
  for (int i = 0; i <= 30000; i++) {
    // if( cnt[i] )cout << i << " " << cnt[i] << endl;
    while (cnt[i]--)
      ans = ans * bigInteger(itos(i));
  }
  cout << ans.str() << endl;
}