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

#define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f

#include <algorithm>
#include <assert.h>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>

using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<double, P> PP;

static const double EPS = 1e-8;

int gcd(int a, int b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

class SternBrocotTree {
public:
  SternBrocotTree(int B, int p)
      : max_depth(0), ans_left_numerator(0), ans_right_numerator(0),
        ans_left_denominator(0), ans_right_denominator(0) {
    this->B = B;
    this->p = p;
  }

  void dfs(int left_numerator, int left_denominator, int right_numerator,
           int right_denominator, int depth) {
    int next_numerator = left_numerator + right_numerator;
    int next_denominator = left_denominator + right_denominator;

    if (contains(left_numerator, left_denominator, next_numerator,
                 next_denominator)) {
      dfs(left_numerator, left_denominator, next_numerator, next_denominator,
          depth + 1);
    }

    if (max_depth < depth) {
      max_depth = depth;
      ans_right_numerator = right_numerator;
      ans_right_denominator = right_denominator;
      ans_left_numerator = left_numerator;
      ans_left_denominator = left_denominator;
    }

    if (contains(next_numerator, next_denominator, right_numerator,
                 right_denominator)) {
      dfs(next_numerator, next_denominator, right_numerator, right_denominator,
          depth + 1);
    }
  }
  void disp() {
    printf("%d/%d %d/%d\\n", ans_right_numerator, ans_right_denominator,
           ans_left_numerator, ans_left_denominator);
  }

private:
  int B;
  int p;
  int max_depth;
  int ans_left_numerator;
  int ans_left_denominator;
  int ans_right_numerator;
  int ans_right_denominator;

  bool contains(int left_numerator, int left_denominator, int right_numerator,
                int right_denominator) {
    if (left_numerator > B || left_denominator > B || right_numerator > B ||
        right_denominator > B)
      return false;
    if (left_numerator * left_numerator <
            left_denominator * left_denominator * p &&
        p * right_denominator * right_denominator <
            right_numerator * right_numerator) {
      return true;
    }
    return false;
  }
};

int main() {
  int p;
  int n;

  while (~scanf("%d %d", &p, &n)) {
    if (p == 0 && n == 0)
      break;
    SternBrocotTree sbt(n, p);
    sbt.dfs(0, 1, 1, 0, 0);
    sbt.disp();
  }
}

Error: MLE

Fixed submission:

#define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f

#include <algorithm>
#include <assert.h>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>

using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<double, P> PP;

static const double EPS = 1e-8;

int gcd(int a, int b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

class Rational {
public:
  ll x;
  ll y;
  Rational(ll x, ll y) : x(x), y(y) {}
  bool operator<(const Rational &r) const {
    // (x*x)/(y*y) < (r.x*r.x)/(r.y*r.y)
    return x * x * r.y * r.y < r.x * r.x * y * y;
  }
  bool operator>(const Rational &r) const {
    return x * x * r.y * r.y > r.x * r.x * y * y;
  }
  bool operator>(const ll v) const { return x * x > v * y * y; }
  bool operator<(const ll v) const {
    // x/y < sqrt(v)
    // (x*x)/(y*y) < v
    // x * x < v * y * y
    return x * x < v * y * y;
  }
};

int main() {
  int p;
  int n;

  while (~scanf("%d %d", &p, &n)) {
    if (p == 0 && n == 0)
      break;

    vector<Rational> rational_numbers;
    for (int numerator = 1; numerator <= n; numerator++) {
      for (int denominator = 1; denominator <= numerator; denominator++) {
        int div = gcd(numerator, denominator);
        int x = numerator / div;
        int y = denominator / div;
        if (x != numerator || y != denominator)
          continue;
        rational_numbers.push_back(Rational(x, y));
      }
    }
    sort(rational_numbers.begin(), rational_numbers.end());

    int i = lower_bound(rational_numbers.begin(), rational_numbers.end(), p) -
            rational_numbers.begin();
    i--;
    int u = rational_numbers[i].x;
    int v = rational_numbers[i].y;

    int x = rational_numbers[i + 1].x;
    int y = rational_numbers[i + 1].y;
    printf("%d/%d %d/%d\\n", x, y, u, v);
  }
}