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

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

int P, Q, A, N;

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

void proc(int &na, int &nb) {
  int lim = gcd(na, nb);
  for (int j = 2; j * j <= lim; j++) {
    if (na % j == 0 && nb % j == 0) {
      na /= j;
      nb /= j;
      j--;
    }
  }
  // if(na==0){
  //   cout<<a<<" "<<b<<" "<<bunbo<<endl;
  // }
  if (nb % na == 0) {
    nb /= na;
    na = 1;
  } else if (na % nb == 0) {
    na /= nb;
    nb = 1;
  }
}

// a/b
int dfs(int cnt, int mul, int a, int b, int bunbo) {
  if (mul == 0)
    return 0;
  else if (a == 0) {
    return 1;
  } else if (cnt == 0)
    return 0;
  int res = 0;
  if (a == 1 && bunbo <= b)
    res += dfs(cnt - 1, mul / b, 0, 1, bunbo);
  for (int i = bunbo; i * i <= mul; i++) {
    if (a == 1 && i == b)
      continue;
    int c = lcm(i, b);
    int nb = c;
    int na = -(c / i) + (a * c / b);
    if (na >= 0) {
      proc(na, nb);
      res += dfs(cnt - 1, mul / i, na, nb, i);
    }
  }
  return res;
}

int main() {
  while (cin >> P >> Q >> A >> N && (P | Q | A | N)) {
    proc(P, Q);
    int res = dfs(N, A, P, Q, 1);
    cout << res << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

class Fraction {
private:
  int numerator;
  int denominator;

private:
  void Reduction() {
    for (int i = 2; i <= min(abs(numerator), abs(denominator)); i++) {
      if (numerator % i == 0 && denominator % i == 0) {
        numerator /= i;
        denominator /= i;
        i--;
      }
    }
  }
  int gcd(int a, int b) {
    if (b == 0)
      return a;
    return gcd(b, a % b);
  }

  int lcm(int a, int b) { return a * b / Fraction::gcd(a, b); }

public:
  Fraction(int numerator_, int denominator_) {
    if (denominator_ == 0)
      throw "excp";
    numerator = numerator_;
    denominator = denominator_;
    Reduction();
  }
  Fraction(const Fraction &f) {
    this->numerator = f.getNumerator();
    this->denominator = f.getDenominator();
  }
  int getNumerator() const { return numerator; }
  int getDenominator() const { return denominator; }
  string toString() const {
    string res;
    stringstream ss1, ss2;
    ss1 << numerator;
    res += ss1.str();
    res += '/';
    ss2 << denominator;
    res += ss2.str();
    return res;
  }
  Fraction &operator*=(const Fraction &f) {
    this->numerator *= f.getNumerator();
    this->denominator *= f.getDenominator();
    Reduction();
    return *this;
  }
  Fraction &operator-=(const Fraction &f) {
    // ツ閉ェツ陛ェツづーツ暗ェツ致ツつウツつケツづつゥツづァ
    int newDenom = lcm(f.getDenominator(), this->denominator);
    int newNume = (newDenom / this->denominator) * this->numerator -
                  (newDenom / f.getDenominator()) * f.getNumerator();
    this->denominator = newDenom;
    this->numerator = newNume;
    Reduction();
    return *this;
  }
  Fraction &operator+=(const Fraction &f) {
    // ツ閉ェツ陛ェツづーツ暗ェツ致ツつウツつケツづつゥツづァ
    int newDenom = Fraction::lcm(f.getDenominator(), this->denominator);
    int newNume = (newDenom / this->denominator) * this->numerator +
                  (newDenom / f.getDenominator()) * f.getNumerator();
    this->denominator = newDenom;
    this->numerator = newNume;
    Reduction();
    return *this;
  }
  Fraction operator*(const Fraction &f) {
    return Fraction(f.getNumerator() * this->getNumerator(),
                    f.getDenominator() * this->getDenominator());
  }
  Fraction operator+(const Fraction &f) {
    int newDenom = Fraction::lcm(f.getDenominator(), this->denominator);
    int newNume = (newDenom / this->denominator) * this->numerator +
                  (newDenom / f.getDenominator()) * f.getNumerator();
    Fraction nf = Fraction(newNume, newDenom);
    return nf;
  }
  Fraction operator-(const Fraction &f) {
    int newDenom = Fraction::lcm(f.getDenominator(), this->denominator);
    int newNume = (newDenom / this->denominator) * this->numerator -
                  (newDenom / f.getDenominator()) * f.getNumerator();
    Fraction nf = Fraction(newNume, newDenom);
    return nf;
  }
};

void yakubun(int &p, int &q) {
  for (int i = 2; i <= min(q, p); i++) {
    if (p % i == 0 && q % i == 0) {
      p /= i;
      q /= i;
      i--;
    }
  }
}
int gcd(int a, int b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}

int lcm(int a, int b) { return a * b / gcd(a, b); }
// ツ暗クツつォツ算ツづーツ行ツつ、
void subOperation(int p, int q, int r, int s, int &np, int &nq) {
  int t = lcm(s, q);
  int u = (t / q) * p - (t / s) * r;
  yakubun(u, t);
  np = u;
  nq = t;
}

#define EPS (1e-10)
int lim;
int cnt;

void dfs(int p, int q, int next, int rem, int a) {
  if (a > lim)
    return;
  else {
    if (p == 1)
      if (a * q <= lim && q >= next)
        cnt++;
    rem--;
    if (rem == 0)
      return;
    if (next * next * a > lim)
      return;
    for (int i = (lim / a); i >= next; i--) {
      if (i * i * a > lim)
        continue;
      int np, nq;
      subOperation(p, q, 1, i, np, nq);
      if (np <= 0)
        break;
      if (i * a * nq <= lim)
        dfs(np, nq, i, rem, i * a);
    }
  }
}

void dfs2(Fraction &f, int next, int rem, int a) {
  if (a > lim)
    return;
  if (f.getNumerator() == 1)
    if (a * f.getDenominator() <= lim && f.getDenominator() >= next)
      cnt++;
  rem--;
  if (rem == 0 || next * next * a > lim)
    return;
  for (int i = (lim / a); i >= next; i--) {
    if (i * i * a > lim)
      continue;
    Fraction f2 = (f - Fraction(1, i));
    if (f2.getNumerator() <= 0)
      break;
    if (i * a * f2.getDenominator() <= lim)
      dfs2(f2, i, rem, i * a);
  }
}

int main() {
  // Fraction f(3,4);
  // Fraction f2(5,4);
  // cout<<(f*f2).toString()<<endl;
  int p, q, a, n;
  while (cin >> p >> q >> a >> n && !(p == 0 && q == 0 && a == 0 && n == 0)) {
    lim = a;
    cnt = 0;
    // yakubun(p,q);
    //  ツ催渉可づ個青板つゥツづァツづづアツづづアツ暗クツつ「ツづつ「ツつュツ催帰
    // dfs(p,q,1,n,1);
    Fraction start(p, q);
    dfs2(start, 1, n, 1);
    printf("%d\\n", cnt);
  }
  return 0;
}