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

#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
using namespace std;

set<vector<int>> S;
int P, Q, A, N;

struct Frac {
  int p, q; // frac{p}{q}
  Frac(int P, int Q) {
    p = P;
    q = Q;
  }
  int gcd(int a, int b) {
    if (b == 0)
      return a;
    return gcd(b, a % b);
  }
  void reduce() {
    int d = gcd(p, q);
    if (d < 0)
      d = -d;
    p /= d;
    q /= d;
  }
  Frac operator*(const Frac &F) {
    Frac ret(p * F.p, q * F.q);
    ret.reduce();
    return ret;
  }
  Frac operator*(int d) {
    Frac ret(p * d, q);
    ret.reduce();
    return ret;
  }
  Frac operator/(const Frac &F) {
    Frac ret(p * F.q, q * F.p);
    ret.reduce();
    return ret;
  }
  Frac operator/(int d) {
    Frac ret(p, q * d);
    ret.reduce();
    return ret;
  }
  Frac operator+(const Frac &F) {
    Frac ret(p * F.q + q * F.p, q * F.q);
    ret.reduce();
    return ret;
  }
  Frac operator+(int d) {
    Frac ret(p + q * d, q);
    ret.reduce();
    return ret;
  }
  Frac operator-(const Frac &F) {
    Frac ret(p * F.q - q * F.p, q * F.q);
    ret.reduce();
    return ret;
  }
  Frac operator-(int d) {
    Frac ret(p - q * d, q);
    ret.reduce();
    return ret;
  }
  bool operator<(const Frac &F) {
    Frac ret(p * F.q - q * F.p, q * F.q);
    ret.reduce();
    return ret.p < 0;
  }
  bool operator<=(const Frac &F) {
    Frac ret(p * F.q - q * F.p, q * F.q);
    ret.reduce();
    return ret.p <= 0;
  }
};

int gcd(int a, int b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}
/*
int rec(int max, int a, int p, int q, int n){
    // if(q*a>A) return 0;
    if(p==0&&n>=0) return 1;
    if(n<0||a>A) return 0;
    int ret=0;
    for(int r=max+1;a*r<=A;r++){
        //for(int k=1,ar=a*r;ar<=A&&Frac(k,r)<=f;k++,ar*=r){
        for(int k=1,ar=a*r;ar<=A&&k*q<=r*p;k++,ar*=r){
            //ret+=rec(r,ar,f-Frac(k,r),n-k);
            int fp=p*r-k*q,fq=q*r;
            int d=gcd(fp,fq);
            if(fq/d*a<=A) ret+=rec(r,ar,fp/d,fq/d,n-k);
        }
    }
    return ret;
}*/

int rec2(int rmin, int p, int q, int n) {
  if (n < 0 || p * Q > q * P)
    return 0;
  if (p * Q == q * P)
    return 1;
  int ret = 0;
  for (int r = rmin; q * r <= A; r++) {
    ret += rec2(r, p * r + q, q * r, n - 1);
  }
  return ret;
}

int main() {
  while (cin >> P >> Q >> A >> N, P) {
    // cout<<rec(0,1,P,Q,N)<<endl;
    cout << rec2(1, 0, 1, N) << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
using namespace std;

set<vector<int>> S;
int P, Q, A, N;

struct Frac {
  int p, q; // frac{p}{q}
  Frac(int P, int Q) {
    p = P;
    q = Q;
  }
  int gcd(int a, int b) {
    if (b == 0)
      return a;
    return gcd(b, a % b);
  }
  void reduce() {
    int d = gcd(p, q);
    if (d < 0)
      d = -d;
    p /= d;
    q /= d;
  }
  Frac operator*(const Frac &F) {
    Frac ret(p * F.p, q * F.q);
    ret.reduce();
    return ret;
  }
  Frac operator*(int d) {
    Frac ret(p * d, q);
    ret.reduce();
    return ret;
  }
  Frac operator/(const Frac &F) {
    Frac ret(p * F.q, q * F.p);
    ret.reduce();
    return ret;
  }
  Frac operator/(int d) {
    Frac ret(p, q * d);
    ret.reduce();
    return ret;
  }
  Frac operator+(const Frac &F) {
    Frac ret(p * F.q + q * F.p, q * F.q);
    ret.reduce();
    return ret;
  }
  Frac operator+(int d) {
    Frac ret(p + q * d, q);
    ret.reduce();
    return ret;
  }
  Frac operator-(const Frac &F) {
    Frac ret(p * F.q - q * F.p, q * F.q);
    ret.reduce();
    return ret;
  }
  Frac operator-(int d) {
    Frac ret(p - q * d, q);
    ret.reduce();
    return ret;
  }
  bool operator<(const Frac &F) {
    Frac ret(p * F.q - q * F.p, q * F.q);
    ret.reduce();
    return ret.p < 0;
  }
  bool operator<=(const Frac &F) {
    Frac ret(p * F.q - q * F.p, q * F.q);
    ret.reduce();
    return ret.p <= 0;
  }
};

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

int rec(int max, int a, int p, int q, int n) {
  // if(q*a>A) return 0;
  if (p == 0 && n >= 0)
    return 1;
  if (n < 0 || a > A)
    return 0;
  int ret = 0;
  for (int r = max + 1; a * r <= A; r++) {
    // for(int k=1,ar=a*r;ar<=A&&Frac(k,r)<=f;k++,ar*=r){
    for (int k = 1, ar = a * r; ar <= A && k * q <= r * p; k++, ar *= r) {
      // ret+=rec(r,ar,f-Frac(k,r),n-k);
      int fp = p * r - k * q, fq = q * r;
      int d = gcd(fp, fq);
      if (d < 0)
        d = -d;
      if (fq / d * a <= A)
        ret += rec(r, ar, fp / d, fq / d, n - k);
    }
  }
  return ret;
}

int main() {
  while (cin >> P >> Q >> A >> N, P) {
    cout << rec(0, 1, P, Q, N) << endl;
  }
  return 0;
}