Problem p00712 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;

#define fst first
#define snd second
#define MP make_pair
#define PB push_back

VI PS, QS, AS, NS, cnts;
int P, Q, A, N;
int T;

VVI have_n_ts;

// p / q

constexpr int MEMO_LIMIT = 2500;
int ymemo[MEMO_LIMIT][MEMO_LIMIT][2] = {};

int p_, q_;

inline void yakubun(int &p, int &q) {
  p_ = p, q_ = q;
  if (p_ < MEMO_LIMIT && q_ < MEMO_LIMIT && ymemo[p_][q_][0]) {
    p = ymemo[p_][q_][0];
    q = ymemo[p_][q_][1];
    return;
  }

  int c = __gcd(p, q);
  if (c == 1)
    return;
  p /= c;
  q /= c;

  if (p_ < MEMO_LIMIT && q_ < MEMO_LIMIT) {
    ymemo[p_][q_][0] = p;
    ymemo[p_][q_][1] = q;
  }
}

inline void add(int p1, int q1, int p2, int q2, int &np, int &nq) {
  np = p1 * q2 + p2 * q1;
  nq = q1 * q2;
  if (np > 0) {
    yakubun(np, nq);
  }
}

inline void sub(int p1, int q1, int p2, int q2, int &np, int &nq) {
  add(p1, q1, -1 * p2, q2, np, nq);
}

int np, nq;
inline void dfs(int p, int q, int a, int n, int before) {
  if (a > 12000)
    return;

  for (int t : have_n_ts[n]) {
    cnts[t] += a <= AS[t] && p == PS[t] && q == QS[t];
  }

  if (n >= 7)
    return;

  for (int i = before; i * a <= 12000; i++) {
    add(p, q, 1, i, np, nq);
    dfs(np, nq, a * i, n + 1, i);
  }
}

int main(void) {
  have_n_ts.resize(8);
  T = 0;
  while (cin >> P >> Q >> A >> N, P) {
    yakubun(P, Q);
    PS.PB(P);
    QS.PB(Q);
    AS.PB(A);
    NS.PB(N);
    for (int i = 1; i <= N; i++) {
      have_n_ts[i].PB(T);
    }
    ++T;
  }

  cnts.resize(T);

  dfs(0, 1, 1, 0, 1);

  for (auto cnt : cnts)
    cout << cnt << endl;

  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<VI> VVI;

#define fst first
#define snd second
#define MP make_pair
#define PB push_back

VI PS, QS, AS, NS, cnts;
int P, Q, A, N;
int T;

VVI have_n_ts;

// p / q

constexpr int MEMO_LIMIT = 5000;
int ymemo[MEMO_LIMIT][MEMO_LIMIT][2] = {};

int p_, q_;

inline void yakubun(int &p, int &q) {
  p_ = p, q_ = q;
  if (p_ < MEMO_LIMIT && q_ < MEMO_LIMIT && ymemo[p_][q_][0]) {
    p = ymemo[p_][q_][0];
    q = ymemo[p_][q_][1];
    return;
  }

  int c = __gcd(p, q);
  if (c == 1)
    return;
  p /= c;
  q /= c;

  if (p_ < MEMO_LIMIT && q_ < MEMO_LIMIT) {
    ymemo[p_][q_][0] = p;
    ymemo[p_][q_][1] = q;
  }
}

inline void add(int p1, int q1, int p2, int q2, int &np, int &nq) {
  np = p1 * q2 + p2 * q1;
  nq = q1 * q2;
  if (np > 0) {
    yakubun(np, nq);
  }
}

inline void sub(int p1, int q1, int p2, int q2, int &np, int &nq) {
  add(p1, q1, -1 * p2, q2, np, nq);
}

int np, nq;
inline void dfs(int p, int q, int a, int n, int before) {
  if (a > 12000)
    return;

  for (int t : have_n_ts[n]) {
    cnts[t] += a <= AS[t] && p == PS[t] && q == QS[t];
  }

  if (n >= 7)
    return;

  if (n == 6) {
    for (int t : have_n_ts[7]) {
      if (AS[t] > a)
        continue;
      sub(PS[t], QS[t], p, q, np, nq);
      cnts[t] += np == 1 && nq * a <= AS[t];
    }

    return;
  }

  for (int i = before; i * a <= 12000; i++) {
    add(p, q, 1, i, np, nq);
    dfs(np, nq, a * i, n + 1, i);
  }
}

int main(void) {
  have_n_ts.resize(8);
  T = 0;
  while (cin >> P >> Q >> A >> N, P) {
    yakubun(P, Q);
    PS.PB(P);
    QS.PB(Q);
    AS.PB(A);
    NS.PB(N);
    for (int i = 1; i <= N; i++) {
      have_n_ts[i].PB(T);
    }
    ++T;
  }

  cnts.resize(T);

  dfs(0, 1, 1, 0, 1);

  for (auto cnt : cnts)
    cout << cnt << endl;

  return 0;
}