Problem:
Problem C:
Unit Fraction Partition
A fraction whose numerator is 1
and whose denominator is a positive integer
is called a unit fraction.
A representation of a positive rational number
p
/
q
as the sum of finitely many unit fractions is called a
partition
of
p
/
q
into unit fractions.
For example,
1/2 + 1/6
is a partition of
2/3
into unit fractions.
The difference in the order of addition is disregarded.
For example, we do not distinguish
1/6 + 1/2
from
1/2 + 1/6.
For given four positive integers
p
,
q
,
a
, and
n
,
count the number
of partitions of
p
/
q
into unit fractions satisfying the following two conditions.
The partition is the sum of at most
n
many unit fractions.
The product of the denominators of the unit fractions in the
partition is less than or equal to
a
.
For example, if
(
p
,
q
,
a
,
n
) = (2,3,120,3),
you should report 4 since
enumerates all of the valid partitions.
Input
The input is a sequence of at most 1000 data sets followed by a terminator.
A data set is a line containing four positive integers
p
,
q
,
a
, and
n
satisfying
p
,
q
<= 800,
a
<= 12000
and
n
<= 7.
The integers are separated by a space.
The terminator is composed of just one line
which contains four zeros separated by a space.
It is not a part of the input data but a mark for the end of the input.
Output
The output should be composed of lines
each of which contains a single integer.
No other characters should appear in the output.
The output integer corresponding to a data set
p
,
q
,
a
,
n
should be the number of all partitions of
p
/
q
into at most
n
many unit fractions such that the product of the denominators of the
unit fractions is less than or equal to
a
.
Sample Input
2 3 120 3
2 3 300 3
2 3 299 3
2 3 12 3
2 3 12000 7
54 795 12000 7
2 3 300 1
2 1 200 5
2 4 54 2
0 0 0 0
Output for the Sample Input
4
7
6
2
42
1
0
9
3

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int n, a;

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

int dfs(int p, int q, int m, int prod, int c) {
	// if (prod * q > a) return 0;
	if (p * m > (n - c) * q) return 0;
	int ret = 0;
	for (int i = m; i * prod <= a; i++) {
		int np = i * p - q, nq = i * q;
		if (np == 0) {
			ret++;
			continue;
		} else if (np < 0) {
			continue;
		}
		if(c < n) {
			int d = gcd(np, nq);
			np /= d;
			nq /= d;
			ret += dfs(np, nq, i, prod * i, c + 1);
		}
	}
	return ret;
}

int main() {
	while (true) {
		int p, q;
		cin >> p >> q;
		cin >> a >> n;
		if (p == 0) break;
		cout << dfs(p, q, 1, 1, 0) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 980
memory_kb: 3132
final_rank: 18

code_snippet: #include <iostream>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
typedef long long int ll;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000001
using namespace std;

int ans,count_MAX;
int P,Q,Limit,common;

void recursive(int bunshi,int bunbo,int pre_add_bunbo,int bunbo_sum,int count){

	if(Q*bunshi == P*bunbo){
		ans++;
		return;
	}
	if(count == count_MAX)return;

	if(Q*bunshi > P*bunbo)return;

	int next_bunshi,next_bunbo;

	for(int i = pre_add_bunbo; bunbo_sum*i <= Limit; i++){

		next_bunshi = bunshi*i+bunbo;
		next_bunbo = bunbo*i;

		recursive(next_bunshi,next_bunbo,i,bunbo_sum*i,count+1);
	}
}

int main(){

	while(true){
        cin >> P >> Q >> Limit >> count_MAX;
		if(P == 0 && Q == 0 && Limit == 0 && count_MAX == 0)break;

		ans = 0;

		recursive(0,1,0,1,0);

		cout << ans << endl;

	}

	return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3368
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define sz(A) (ll)(A.size())
ll f(ll P,ll Q,ll A,ll N,ll c){
    if(P==0)return 1;
    if(c>A)return 0;
    ll ans=0;
    while(1){
        ans+=f(P,Q,A,N,c+1);
        if(A<c||N==0||c*P<Q)break;
        A/=c;N--;
        P=c*P-Q;Q*=c;
    }
    return ans;
}
int main(){
    while(1){
        ll P,Q,A,N;cin>>P>>Q>>A>>N;
        if(!P)return 0;
        ll g=__gcd(P,Q);
        P/=g;Q/=g;
        cout<<f(P,Q,A,N,1)<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 4196
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
int f(int p, int q, int a, int n, int prod, int low) {
  if (p == 0) {
    return 1;
  }
  if (p < 0 || n == 0) {
    return 0;
  }
  int ans = 0;
  for (int i = low; i * prod <= a; i++) {
    //p/q - 1/i -> (p * i - q) / q * i
    ans += f(p * i - q, q * i, a, n - 1, prod * i, i);
  }
  return ans;
}
int main() {
  while (1) {
    int p, q, a, n;
    cin >> p >> q >> a >> n;
    if (p == 0 && q == 0 && a == 0 && n == 0) {
      break;
    }
    cout << f(p, q, a, n ,1, 1) << '\n';
  }
}
accuracy: 1
time_ms: 110
memory_kb: 3132
final_rank: 3

code_snippet: /// 生成AI不使用 / Not using generative AI

// #pragma GCC target ("avx")
// #pragma GCC optimize("Ofast")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#ifdef MARC_LOCAL
#define _GLIBCXX_DEBUG
#endif

#ifdef ATCODER
#include <atcoder/all>
using namespace atcoder;
#endif

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

//#define int long long
using ll = long long; using vll = vector<ll>; using vvll = vector<vll>; using vvvll = vector<vvll>; using vvvvll = vector<vvvll>;
using vi = vector<int>; using vvi = vector<vi>; using vvvi = vector<vvi>; using vvvvi = vector<vvvi>;
using ld = long double; using vld = vector<ld>; using vvld = vector<vld>; using vd = vector<double>;
using vc = vector<char>; using vvc = vector<vc>; using vs = vector<string>;
using vb = vector<bool>; using vvb = vector<vb>; using vvvb = vector<vvb>;
using pii = pair<int, int>; using pcc = pair<char, char>; using pll = pair<ll, ll>; using pli = pair<ll, int>; using pdd = pair<double, double>; using pldld = pair<ld,ld>;
using vpii = vector<pii>; using vvpii = vector<vpii>; using vpll = vector<pll>; using vvpll = vector<vpll>; using vpldld = vector<pldld>;
using ui = unsigned int; using ull = unsigned long long;
using i128 = __int128; using f128 = __float128;
template<class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define vv(type, name, h, ...) vector<vector<type> > name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...) vector<vector<vector<type> > > name(h, vector<vector<type> >(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...) vector<vector<vector<vector<type> > > > name(a, vector<vector<vector<type> > >(b, vector<vector<type> >(c, vector<type>(__VA_ARGS__))))

#define overload4(a,b,c,d,name,...) name
#define rep1(n) for(ll i = 0; i < (ll)n; i++)
#define rep2(i,n) for(ll i = 0; i < (ll)n; i++)
#define rep3(i,a,b) for (ll i = a; i < (ll)b; i++)
#define rep4(i,a,b,c) for (ll i = a; i < (ll)b; i += (ll)c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define repback1(n) for (ll i = (ll)n-1; i >= 0; i--)
#define repback2(i,n) for (ll i = (ll)n-1; i >= 0; i--)
#define repback3(i,a,b) for (ll i = (ll)b-1; i >= (ll)a; i--)
#define repback4(i,a,b,c) for (ll i = (ll)b-1; i >= (ll)a; i -= (ll)c)
#define repback(...) overload4(__VA_ARGS__,repback4,repback3,repback2,repback1)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
#define include(y, x, H, W) (0 <= (y) && (y) < (H) && 0 <= (x) && (x) < (W))
#define inrange(x, down, up) ((down) <= (x) && (x) <= (up))
#define pb push_back
#define eb emplace_back
#define fir first
#define sec second
#define TIMER_START TIME_START = clock()
#ifdef MARC_LOCAL
// https://trap.jp/post/1224/
#define debug1(x) cout << "debug: " << (#x) << ": " << (x) << endl
#define debug2(x, y) cout << "debug: " << (#x) << ": " << (x) << ", " << (#y) << ": " << (y) << endl
#define debug3(x, y, z) cout << "debug: " << (#x) << ": " << (x) << ", " << (#y) << ": " << (y) << ", " << (#z) << ": " << (z) << endl
#define debug4(x, y, z, w) cout << "debug: " << (#x) << ": " << (x) << ", " << (#y) << ": " << (y) << ", " << (#z) << ": " << (z) << ", " << (#w) << ": " << (w) << endl
#define debug5(x, y, z, w, v) cout << "debug: " << (#x) << ": " << (x) << ", " << (#y) << ": " << (y) << ", " << (#z) << ": " << (z) << ", " << (#w) << ": " << (w) << ", " << (#v) << ": " << (v) << endl
#define debug6(x, y, z, w, v, u) cout << "debug: " << (#x) << ": " << (x) << ", " << (#y) << ": " << (y) << ", " << (#z) << ": " << (z) << ", " << (#w) << ": " << (w) << ", " << (#v) << ": " << (v) << ", " << (#u) << ": " << (u) << endl
#define overload6(a, b, c, d, e, f, g,...) g
#define debug(...) overload6(__VA_ARGS__, debug6, debug5, debug4, debug3, debug2, debug1)(__VA_ARGS__)
#define debuga cerr << "a" << endl
#define debugnl cout << endl
#define Case(i) cout << "Case #" << (i) << ": "
#define TIMECHECK cerr << 1000.0 * static_cast<double>(clock() - TIME_START) / CLOCKS_PER_SEC << "ms" << endl
#define LOCAL 1
#else
#define debug1(x) void(0)
#define debug2(x, y) void(0)
#define debug3(x, y, z) void(0)
#define debug4(x, y, z, w) void(0)
#define debug5(x, y, z, w, v) void(0)
#define debug6(x, y, z, w, v, u) void(0)
#define debug(...) void(0)
#define debuga void(0)
#define debugnl void(0)
#define Case(i) void(0)
#define TIMECHECK void(0)
#define LOCAL 0
#endif

//mt19937_64 rng(0);
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
clock_t TIME_START;
const long double pi = 3.141592653589793238462643383279L;
const long long INFL = 1000000000000000000ll;
const long long INFLMAX = numeric_limits< long long >::max(); // 9223372036854775807
const int INF = 1000000000;
const int INFMAX = numeric_limits< int >::max(); // 2147483647
const long double INFD = numeric_limits<ld>::infinity();
const long double EPS = 1e-10;
const int mod1 = 1000000007;
const int mod2 = 998244353;
const vi dx1 = {1,0,-1,0};
const vi dy1 = {0,1,0,-1};
const vi dx2 = {0, 1, 1, 1, 0, -1, -1, -1};
const vi dy2 = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr char nl = '\n';
constexpr char bl = ' ';

std::ostream &operator<<(std::ostream &dest, __int128_t value) { std::ostream::sentry s(dest); if (s) {__uint128_t tmp = value < 0 ? -value : value; char buffer[128]; char *d = std::end(buffer); do {--d;*d = "0123456789"[tmp % 10];tmp /= 10;} while (tmp != 0);if (value < 0) {--d;*d = '-';}int len = std::end(buffer) - d;if (dest.rdbuf()->sputn(d, len) != len) {dest.setstate(std::ios_base::badbit);}}return dest; }
__int128 parse(string &s) { __int128 ret = 0; for (int i = 0; i < (int)s.length(); i++) if ('0' <= s[i] && s[i] <= '9') ret = 10 * ret + s[i] - '0'; return ret; } // for __int128 (https://kenkoooo.hatenablog.com/entry/2016/11/30/163533)
template<class T> ostream& operator << (ostream& os, vector<T>& vec) { os << "["; for (int i = 0; i<(int)vec.size(); i++) { os << vec[i] << (i + 1 == (int)vec.size() ? "" : ", "); } os << "]"; return os; } /// vector 出力
template<class T, class U> ostream& operator << (ostream& os, pair<T, U>& pair_var) { os << "(" << pair_var.first << ", " << pair_var.second << ")"; return os; } // pair 出力
template<class T, class U> ostream& operator << (ostream& os, map<T, U>& map_var) { os << "{"; for (auto itr = map_var.begin(); itr != map_var.end(); itr++) { os << "(" << itr->first << ", " << itr->second << ")"; itr++; if(itr != map_var.end()) os << ", "; itr--; } os << "}"; return os; } // map出力
template<class T> ostream& operator << (ostream& os, set<T>& set_var) { os << "{"; for (auto itr = set_var.begin(); itr != set_var.end(); itr++) { os << *itr; ++itr; if(itr != set_var.end()) os << ", "; itr--; } os << "}"; return os; } /// set 出力

bool equals(long double a, long double b) { return fabsl(a - b) < EPS; }
template<class T> int sign(T a) { return equals(a, 0) ? 0 : a > 0 ? 1 : -1; }
long double radian_to_degree(long double r) { return (r * 180.0 / pi); }
long double degree_to_radian(long double d) { return (d * pi / 180.0); }

int popcnt(unsigned long long a){ return __builtin_popcountll(a); } // ll は 64bit対応！
int MSB1(unsigned long long x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); } // MSB(1), 0-indexed ( (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2) )
int LSB1(unsigned long long x) { return (x == 0 ? -1 : __builtin_ctzll(x)); } // LSB(1), 0-indexed ( (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2) )
long long maskbit(int n) { return (1LL << n) - 1; }
bool bit_is1(long long x, int i) { return ((x>>i) & 1); }
string charrep(int n, char c) { return std::string(n, c); }
template<class T> T square(T x) { return (x) * (x); }
template<class T>void UNIQUE(T& A) {sort(all(A)); A.erase(unique(all(A)), A.end());}
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T, class U> bool chmin(T& a, const U& b){ return chmin(a, (T)b); }
template<class T, class U> bool chmax(T& a, const U& b){ return chmax(a, (T)b); }
void YESNO(bool b) {if(b){cout<<"YES"<<'\n';} else{cout<<"NO"<<'\n';}} void YES() {YESNO(true);} void NO() {YESNO(false);}
void yesno(bool b) {if(b){cout<<"yes"<<'\n';} else{cout<<"no"<<'\n';}} void yes() {yesno(true);} void no() {yesno(false);}
void YesNo(bool b) {if(b){cout<<"Yes"<<'\n';} else{cout<<"No"<<'\n';}} void Yes() {YesNo(true);} void No() {YesNo(false);}
void POSIMPOS(bool b) {if(b){cout<<"POSSIBLE"<<'\n';} else{cout<<"IMPOSSIBLE"<<'\n';}}
void PosImpos(bool b) {if(b){cout<<"Possible"<<'\n';} else{cout<<"Impossible"<<'\n';}}
void posimpos(bool b) {if(b){cout<<"possible"<<'\n';} else{cout<<"impossible"<<'\n';}}
void FIRSEC(bool b) {if(b){cout<<"FIRST"<<'\n';} else{cout<<"SECOND"<<'\n';}}
void firsec(bool b) {if(b){cout<<"first"<<'\n';} else{cout<<"second"<<'\n';}}
void FirSec(bool b) {if(b){cout<<"First"<<'\n';} else{cout<<"Second"<<'\n';}}
void AliBob(bool b) {if(b){cout<<"Alice"<<'\n';} else{cout<<"Bob"<<'\n';}}
void TakAok(bool b) {if(b){cout<<"Takahashi"<<'\n';} else{cout<<"Aoki"<<'\n';}}
int GetTime() {return 1000.0*static_cast<double>(clock() - TIME_START) / CLOCKS_PER_SEC;}
ll myRand(ll B) {return (unsigned long long)rng() % B;}
template<class T> void print(const T& x, const char endch = '\n') { cout << x << endch; }

template<class T> T ceil_div(T x, T y) { assert(y); return (x > 0 ? (x + y - 1) / y : x / y); }
template<class T> T floor_div(T x, T y) { assert(y); return (x > 0 ? x / y : (x - y + 1) / y); }
template<class T> pair<T, T> divmod(T x, T y) { T q = floor_div(x, y); return {q, x - q * y}; } /// (q, r) s.t. x = q*y + r 
ll GCD(ll a, ll b) { if(a < b) swap(a, b); if(b == 0) return a; if(a%b == 0) return b; else return GCD(b, a%b); }
ll LCM(ll a, ll b) { assert(GCD(a,b) != 0); return a / GCD(a, b) * b; }
ll MOD(ll &x, const ll P) { ll ret = x%P; if(ret < 0) ret += P; return x = ret; } /// x % P を非負整数に直す
ll mpow(ll x, ll n, const ll mod) { x %= mod; ll ret = 1; while(n > 0) { if(n & 1) ret = ret * x % mod; x = x * x % mod; n >>= 1; } return ret; } /// x^n % mod を計算
ll lpow(ll x, ll n) { ll ret = 1; while(n > 0){ if(n & 1) ret = ret * x; x = x * x; n >>= 1; } return ret; } /// x^nを計算
string toBinary(ll n) { if(n == 0) return "0"; assert(n > 0); string ret; while (n != 0){ ret += ( (n & 1) == 1 ? '1' : '0' ); n >>= 1; } reverse(ret.begin(), ret.end()); return ret; } /// 10進数(long long) -> 2進数(string)への変換
ll toDecimal(string S) { ll ret = 0; for(int i = 0; i < (int)S.size(); i++){ ret *= 2LL; if(S[i] == '1') ret += 1; } return ret; } /// 2進数(string)　→　10進数(long long)への変換
int ceil_pow2(ll n) { int x = 0; while ((1ll << x) < n) x++; return x;} /// return minimum non-negative `x` s.t. `n <= 2**x`
int floor_pow2(ll n) { int x = 0; while ((1ll << (x+1)) <= n) x++; return x;} /// return maximum non-negative `x` s.t. `n >= 2**x`


// ############################
// #                          #
// #    C O D E  S T A R T    #
// #                          #
// ############################

vector<pii > factorization(long long N) {
    vector<pii > ret;
    for (long long i = 2; i * i <= N; i++) {
        int cnt = 0;
        while (N % i == 0) {
            cnt++;
            N /= i;
        }
        if (cnt > 0) ret.emplace_back(i, cnt);
    }
    if (N != 1) ret.emplace_back(N, 1);
    return ret;
}

vector<int> enum_divisors(long long N, const bool do_sort = true) {
    vector<int> ret;

    for (long long i = 1; i * i <= N; i++) {
        if (N % i != 0) continue;
        ret.push_back(i);
        if (i * i != N) ret.push_back(N / i);
    }

    if (do_sort) sort(ret.begin(), ret.end(), greater<int>());
    return ret;
}

/// main()の中に0を受け取る変数（終了判定）を定義しておく
int P,Q,A,N;

void solve() {
    cin >> Q >> A >> N;

    int G = GCD(P,Q);
    P/=G;
    Q/=G;

    // auto baseD = factorization(Q);
    // unordered_map<int,int> mp;
    // for(auto [x,v]:baseD) mp[x] = v;
    
    int ans = 0;
    vb did(A+1,false);
    vvi Ds(A+1);
    for(int i=1; Q*i<=A; i++) { // 分母の積全探索
        // auto tmpD = factorization(i);
        // auto D = mp;
        // for(auto [x,v]) D[x] += v;

        int bunbo = Q*i;
        int need = P*i;

        auto D = enum_divisors(bunbo);
        Ds[bunbo] = D;
        did[bunbo] = true;
        auto dfs = [&](auto dfs, int cnt, int sum, int prev, int prod)->void{
            if(sum == need) {
                if(prod == bunbo) {
                    debug(cnt,sum,prev,prod);
                    ans++;
                }
                return;
            }

            if(cnt == N-1) {
                int tmp = need - sum;
                if(tmp == prod && prev <= bunbo/tmp) {
                    debug(bunbo,sum,prev,prod,tmp);
                    ans++;
                }
                return;
            }

            int tmp = bunbo/prod;
            if(!did[tmp]) {
                did[tmp] = true;
                Ds[tmp] = enum_divisors(tmp);
            }

            for(auto nxt:Ds[tmp]) { // 1/nxtを足す
                if(prev>nxt) break;
                if(sum + bunbo/nxt > need) break;
                
                dfs(dfs, cnt+1, sum+bunbo/nxt, nxt, prod*nxt);
            }
        };
        dfs(dfs, 0, 0, 0, 1);

    }

    cout << ans << nl;
}



signed main() {
    cin.tie(0); ios_base::sync_with_stdio(false);
    TIMER_START;
    //cout << fixed << setprecision(15);
    

    //int tt = 1;
    //cin >> tt;
    while(true){
        cin >> P;
        if(P == 0) break;

        solve();
    }

    TIMECHECK;
    return 0;
}
accuracy: 1
time_ms: 680
memory_kb: 4344
final_rank: 20

code_snippet: #include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int p,q,a,n,t=0;
void fun(int k,int last,int sum1,int sum2)
{
	if(k<=n+1)
	{
			if(sum1*q==sum2*p)
			{
				t++;
				return;
			}
			if((sum1*q>=sum2*p))return;
				for(int i=last;i<=a;++i)
				if(sum2*i<=a)fun(k+1,i,sum1*i+sum2,sum2*i);else break;
	}
}
int main()
{
	while(1==1)
	{
		scanf("%d%d%d%d",&p,&q,&a,&n);
		if(p==0 && q==0 && a==0 && n==0)return 0;
		else
		{
			t=0;
			fun(1,q/p,0,1);
			cout<<t<<endl;
		}
	}
}
accuracy: 1
time_ms: 110
memory_kb: 3112
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
int ans = 0;
void search_ans(int p, int q, int a, int n, int r, int m, int c, int s) {
  if (q * c == p * m) {
    ans++;
    return;
  }
  if (s == n) return;
  if (q * c > p * m) return;
  for (int x = r; x * m <= a; x++) {
    int nm = m * x;
    int nc = c * x + m;
    search_ans(p, q, a, n, x, nm, nc, s + 1);
  }
}

int main() {
  vector<int> rep;
  while (true) {
    int p, q, a, n;
    cin >> p >> q >> a >> n;
    if (p == 0 && q == 0 && a == 0 && n == 0) break;

    int r, m, c, s;
    r = m = 1;
    c = s = 0;
    search_ans(p, q, a, n, r, m, c, s);
    rep.push_back(ans);
    ans = 0;
  }
  for (auto v : rep) cout << v << endl;
}
accuracy: 1
time_ms: 100
memory_kb: 3348
final_rank: 7

code_snippet: // #define NDEBUG
#include <bits/stdc++.h>

#define REP_(i, a_, b_, a, b, ...) for (int i = (a), END_##i = (b); i < END_##i; ++i)
#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define ALL(x) std::begin(x), std::end(x)
using Int = long long;
using Uint = unsigned long long;
using Real = long double;

template<typename T, typename U>
inline bool chmax(T &a, U b) { return a < b and ((a = b), true); }
template<typename T, typename U>
inline bool chmin(T &a, U b) { return a > b and ((a = b), true); }
template<typename T>
constexpr T
kBig = std::numeric_limits<T>::max() / 2;
#if __cplusplus < 202002L
template<typename T>
inline int ssize(const T &a) { return (int) a.size(); }
#endif

struct CastInput {
  template<typename T>
  operator T() const {
    T x;
    std::cin >> x;
    assert(bool(std::cin));
    return x;
  }
  struct Sized {
    int n;
    template<typename T>
    operator T() const {
      T xs(n);
      for (auto &x: xs) {
        std::cin >> x;
        assert(bool(std::cin));
      }
      return xs;
    }
  };
  Sized operator()(int n) const { return {n}; }
} in;

template<typename Container>
std::ostream &out_seq(const Container &seq, const char *sep = " ",
                      const char *ends = "\n", std::ostream &os = std::cout) {
  const auto itl = std::begin(seq), itr = std::end(seq);
  for (auto it = itl; it != itr; ++it) {
    if (it != itl) os << sep;
    os << *it;
  }
  return os << ends;
}

template<typename T>
std::ostream &out_one(const T &x, char endc) {
  if constexpr(std::is_same<T, bool>::value)
  {
    return std::cout << (x ? "Yes" : "No") << endc;
  } else {
    return std::cout << x << endc;
  }
}
template<typename T>
std::ostream &out(const T &x) {
  return out_one(x, '\n');
}
template<typename T, typename... Ts>
std::ostream &out(const T &head, Ts... tail) {
  return out_one(head, ' '), out(tail...);
}

void init_(bool interactive = false) {
  std::ios::sync_with_stdio(false);
  if (not interactive) std::cin.tie(nullptr);
  std::cout << std::fixed << std::setprecision(18);
}

[[noreturn]] void exit_() {
#ifdef MY_DEBUG
  std::string _;
  assert((std::cin >> _).fail());
#endif
  std::cout.flush(), std::cerr.flush(), std::_Exit(0);
}

#ifdef MY_DEBUG
#include "debug_dump.hpp"
#include "backward.hpp"
backward::SignalHandling kSignalHandling;
#else
#define DUMP(...)
#define test_case(...)
#define cerr if(false)cerr
#endif

template<class F>
struct Rec {
  F f_;
  explicit Rec(F f) : f_(std::move(f)) {}
  template<class... Args>
  decltype(auto)
  operator()(Args &&... args) {
    return f_(*this, std::forward<Args>(args)...);
  }
};
template<class F> Rec(F) -> Rec<F>;

// Rational number with lazy reduction.
struct LazyRational {
  using i64 = long long;
  using i128 = __int128_t;

  mutable i64 nume_;
  mutable i64 deno_;
  mutable bool reduced_;

  static constexpr i64
  kReduceThreshold = i64(1) << 62;

  LazyRational() : nume_(0), deno_(1), reduced_(true) {}
  LazyRational(i64 n) : nume_(n), deno_(1), reduced_(true) {}
  LazyRational(i64 n, i64 d, bool reduced)
      : nume_(n), deno_(d), reduced_(reduced) {}

  template<typename T>
  LazyRational(T n, T d) : reduced_(false) {
    assert(d != 0);  // zero division
    if (n == 0) {
      d = 1;
      reduced_ = true;
    } else {
      reduced_ = light_reduce_(n, d);
    }
    nume_ = static_cast<i64>(n);
    deno_ = static_cast<i64>(d);
  }

  i64 numerator() const {
    if (not reduced_) {
      reduce_(nume_, deno_);
      reduced_ = true;
    }
    return nume_;
  }

  i64 denominator() const {
    if (not reduced_) {
      reduce_(nume_, deno_);
      reduced_ = true;
    }
    return deno_;
  }

  // Cast to a floating point number.
  template<typename Float>
  explicit operator Float() const {
    static_assert(std::is_floating_point<Float>::value);
    return (Float) nume_ / (Float) deno_;
  }

  const LazyRational &operator+() const { return *this; }

  LazyRational operator-() const {
    return LazyRational(-nume_, deno_, reduced_);
  }

  LazyRational &operator+=(const LazyRational &y) {
    if (y.nume_ == 0) return *this;
    if (this->nume_ == 0) {
      *this = y;
      return *this;
    }
    i128 zn = i128(this->nume_) * y.deno_ + i128(y.nume_) * this->deno_;
    i128 zd = i128(this->deno_) * y.deno_;
    this->reduced_ = light_reduce_(zn, zd);
    this->nume_ = static_cast<i64>(zn);
    this->deno_ = static_cast<i64>(zd);
    return *this;
  }
  friend LazyRational operator+(LazyRational x, const LazyRational &y) {
    x += y;
    return x;
  }

  friend LazyRational operator-(const LazyRational &x, const LazyRational &y) {
    return x + (-y);
  }
  LazyRational &operator-=(const LazyRational &y) {
    *this += -y;
    return *this;
  }

  LazyRational &operator*=(const LazyRational &y) {
    if (this->nume_ == 0) return *this;
    if (y.nume_ == 0) {
      this->nume_ = 0;
      this->deno_ = 1;
      this->reduced_ = true;
    } else {
      i128 zn = i128(this->nume_) * y.nume_;
      i128 zd = i128(this->deno_) * y.deno_;
      this->reduced_ = light_reduce_(zn, zd);
      this->nume_ = static_cast<i64>(zn);
      this->deno_ = static_cast<i64>(zd);
    }
    return *this;
  }
  friend LazyRational operator*(LazyRational x, const LazyRational &y) {
    x *= y;
    return x;
  }

  LazyRational inv() const {
    int sign = this->nume_ >= 0 ? 1 : -1;
    return LazyRational(this->deno_ * sign, this->nume_ * sign, this->reduced_);
  }
  friend LazyRational operator/(const LazyRational &x, const LazyRational &y) {
    return x * y.inv();
  }
  LazyRational &operator/=(const LazyRational &y) {
    *this *= y.inv();
    return *this;
  }

  friend bool operator==(const LazyRational &x, const LazyRational &y) {
    return i128(x.nume_) * y.deno_ == i128(x.deno_) * y.nume_;
  }
  friend bool operator!=(const LazyRational &x, const LazyRational &y) {
    return not(x == y);
  }
  friend bool operator<(const LazyRational &x, const LazyRational &y) {
    return i128(x.nume_) * y.deno_ < i128(x.deno_) * y.nume_;
  }
  friend bool operator>(const LazyRational &x, const LazyRational &y) {
    return y < x;
  }
  friend bool operator<=(const LazyRational &x, const LazyRational &y) {
    return not(x > y);
  }
  friend bool operator>=(const LazyRational &x, const LazyRational &y) {
    return not(x < y);
  }

  friend std::ostream &operator<<(std::ostream &os, const LazyRational &x) {
    return os << x.numerator() << "/" << x.denominator();
  }

 private:
  template<typename T>
  static void reduce_(T &n, T &d) {
    if (n == 0) {
      d = 1;
      return;
    }
    i128 a = abs_(n), b = d;
    while (b) {
      a %= b;
      std::swap(a, b);
    }
    if (a > 1) {
      n /= static_cast<T>(a);
      d /= static_cast<T>(a);
    }
  }

  // Returns whether the args are reduced.
  template<typename T>
  static bool light_reduce_(T &n, T &d) {
    if (std::max<T>(abs_(n), d) <= kReduceThreshold) {
      return false;
    }
    reduce_(n, d);
    if constexpr(std::is_same_v < T, i128 > )
    {
      if (std::max<T>(abs_(n), d) > std::numeric_limits<i64>::max()) {
        throw std::overflow_error("cannot fit in 64 bits");
      }
    }
    return true;
  }

  template<typename T>
  static T abs_(const T &x) {
    if constexpr(std::is_same_v < T, i128 > )
    {
      return x < 0 ? -x : x;
    } else {
      return std::abs(x);
    }
  }
};
using Rat = LazyRational;

template<class T>
T ceil_div(T x, T y) {
  assert(y != 0);
  return x / y + (((x ^ y) >= 0) and (x % y));
}

using namespace std;

auto solve() -> Int {
  int p = in, q = in, a = in, n = in;
  if (p == 0 and q == 0 and a == 0 and n == 0) {
    exit_();
  }

  auto f = Rec([&](auto &rec, int i, const Rat &r, Int d0, Int prod) -> Int {
    if (r.nume_ == 0) return 1;
    if (i == 0) return 0;
    Int res = 0;
    for (Int d = max<Int>(d0, ceil_div(r.deno_, r.nume_)); prod * d <= a; ++d) {
      res += rec(i - 1, r - Rat(1LL, d), d, prod * d);
    }
    return res;
  });
  return f(n, Rat(p, q), 1, 1);
}

int main() {
  init_();
  for (int t = 0;; ++t) {
    test_case(t, 0);
    out(solve());
  }
}
accuracy: 1
time_ms: 860
memory_kb: 3184
final_rank: 17

code_snippet: // #define NDEBUG
#include <bits/stdc++.h>

#define REP_(i, a_, b_, a, b, ...) for (int i = (a), END_##i = (b); i < END_##i; ++i)
#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define ALL(x) std::begin(x), std::end(x)
using Int = long long;
using Uint = unsigned long long;
using Real = long double;

template<typename T, typename U>
inline bool chmax(T &a, U b) { return a < b and ((a = b), true); }
template<typename T, typename U>
inline bool chmin(T &a, U b) { return a > b and ((a = b), true); }
template<typename T>
constexpr T kBig = std::numeric_limits<T>::max() / 2;
#if __cplusplus < 202002L
template<typename T>
inline int ssize(const T &a) { return (int) a.size(); }
#endif

struct CastInput {
  template<typename T>
  operator T() const {
    T x;
    std::cin >> x;
    assert(bool(std::cin));
    return x;
  }
  struct Sized {
    int n;
    template<typename T>
    operator T() const {
      T xs(n);
      for (auto &x: xs) {
        std::cin >> x;
        assert(bool(std::cin));
      }
      return xs;
    }
  };
  Sized operator()(int n) const { return {n}; }
} in;

template<typename Container>
std::ostream &out_seq(const Container &seq, const char *sep = " ",
                      const char *ends = "\n", std::ostream &os = std::cout) {
  const auto itl = std::begin(seq), itr = std::end(seq);
  for (auto it = itl; it != itr; ++it) {
    if (it != itl) os << sep;
    os << *it;
  }
  return os << ends;
}

template<typename T>
std::ostream &out_one(const T &x, char endc) {
  if constexpr (std::is_same<T, bool>::value) {
    return std::cout << (x ? "Yes" : "No") << endc;
  } else {
    return std::cout << x << endc;
  }
}
template<typename T>
std::ostream &out(const T &x) {
  return out_one(x, '\n');
}
template<typename T, typename... Ts>
std::ostream &out(const T &head, Ts... tail) {
  return out_one(head, ' '), out(tail...);
}

void init_(bool interactive = false) {
  std::ios::sync_with_stdio(false);
  if (not interactive) std::cin.tie(nullptr);
  std::cout << std::fixed << std::setprecision(18);
}

[[noreturn]] void exit_() {
#ifdef MY_DEBUG
  std::string _;
  assert((std::cin >> _).fail());
#endif
  std::cout.flush(), std::cerr.flush(), std::_Exit(0);
}

#ifdef MY_DEBUG
#include "debug_dump.hpp"
#include "backward.hpp"
backward::SignalHandling kSignalHandling;
#else
#define DUMP(...)
#define test_case(...)
#define cerr if(false)cerr
#endif

template<class F>
struct Rec {
  F f_;
  explicit Rec(F f) : f_(std::move(f)) {}
  template<class... Args>
  decltype(auto) operator()(Args &&... args) {
    return f_(*this, std::forward<Args>(args)...);
  }
};
template<class F> Rec(F) -> Rec<F>;

// Rational number with lazy reduction.
struct LazyRational {
  using i64 = long long;
  using i128 = __int128_t;

  mutable i64 nume_;
  mutable i64 deno_;
  mutable bool reduced_;

  static constexpr i64 kReduceThreshold = i64(1) << 62;

  LazyRational() : nume_(0), deno_(1), reduced_(true) {}
  LazyRational(i64 n) : nume_(n), deno_(1), reduced_(true) {}

  template<typename T>
  LazyRational(T n, T d) : reduced_(false) {
    assert(d != 0);  // zero division
    if (n == 0) {
      d = 1;
      reduced_ = true;
    } else {
      reduced_ = light_reduce_(n, d);
    }
    nume_ = static_cast<i64>(n);
    deno_ = static_cast<i64>(d);
  }

  i64 numerator() const {
    if (not reduced_) reduce_me_();
    return nume_;
  }

  i64 denominator() const {
    if (not reduced_) reduce_me_();
    return deno_;
  }

  // Cast to a floating point number.
  template<typename Float>
  explicit operator Float() const {
    static_assert(std::is_floating_point<Float>::value);
    return (Float) nume_ / (Float) deno_;
  }

  const LazyRational &operator+() const { return *this; }

  LazyRational operator-() const {
    LazyRational ret;
    ret.nume_ = -this->nume_;
    ret.deno_ = this->deno_;
    ret.reduced_ = this->reduced_;
    return ret;
  }

  friend bool operator==(const LazyRational &x, const LazyRational &y) {
    return i128(x.nume_) * y.deno_ == i128(x.deno_) * y.nume_;
  }
  friend bool operator!=(const LazyRational &x, const LazyRational &y) {
    return not(x == y);
  }
  friend bool operator<(const LazyRational &x, const LazyRational &y) {
    return i128(x.nume_) * y.deno_ < i128(x.deno_) * y.nume_;
  }
  friend bool operator>(const LazyRational &x, const LazyRational &y) { return y < x; }
  friend bool operator<=(const LazyRational &x, const LazyRational &y) {
    return not(x > y);
  }
  friend bool operator>=(const LazyRational &x, const LazyRational &y) {
    return not(x < y);
  }

  LazyRational &operator+=(const LazyRational &y) {
    i128 zn = i128(this->nume_) * y.deno_ + i128(y.nume_) * this->deno_;
    i128 zd = i128(this->deno_) * y.deno_;
    this->reduced_ = light_reduce_(zn, zd);
    this->nume_ = static_cast<i64>(zn);
    this->deno_ = static_cast<i64>(zd);
    return *this;
  }
  friend LazyRational operator+(LazyRational x, const LazyRational &y) {
    x += y;
    return x;
  }

  friend LazyRational operator-(const LazyRational &x, const LazyRational &y) {
    return x + (-y);
  }
  LazyRational &operator-=(const LazyRational &y) {
    *this += -y;
    return *this;
  }

  LazyRational &operator*=(const LazyRational &y) {
    if (this->nume_ == 0) return *this;
    if (y.nume_ == 0) {
      this->nume_ = 0;
      this->deno_ = 1;
      this->reduced_ = true;
      return *this;
    }
    i128 zn = i128(this->nume_) * y.nume_;
    i128 zd = i128(this->deno_) * y.deno_;
    this->reduced_ = light_reduce_(zn, zd);
    this->nume_ = static_cast<i64>(zn);
    this->deno_ = static_cast<i64>(zd);
    return *this;
  }
  friend LazyRational operator*(LazyRational x, const LazyRational &y) {
    x *= y;
    return x;
  }

  LazyRational inv() const {
    LazyRational ret;
    int sign = this->nume_ >= 0 ? 1 : -1;
    ret.nume_ = this->deno_ * sign;
    ret.deno_ = this->nume_ * sign;
    ret.reduced_ = this->reduced_;
    return ret;
  }
  friend LazyRational operator/(const LazyRational &x, const LazyRational &y) {
    return x * y.inv();
  }
  LazyRational &operator/=(const LazyRational &y) {
    *this *= y.inv();
    return *this;
  }

  friend std::ostream &operator<<(std::ostream &os, const LazyRational &x) {
    return os << x.numerator() << "/" << x.denominator();
  }

 private:
  template<typename T>
  static void reduce_(T &n, T &d) {
    if (n == 0) {
      d = 1;
      return;
    }
    i128 a = (n < 0 ? -n : n), b = d;
    while (b) {
      a %= b;
      std::swap(a, b);
    }
    n /= static_cast<T>(a);
    d /= static_cast<T>(a);
  }

  // Returns whether the args are reduced.
  template<typename T>
  static bool light_reduce_(T &n, T &d) {
    if (std::max<T>((n < 0 ? -n : n), d) <= kReduceThreshold) {
      return false;
    }
    reduce_(n, d);
    if constexpr (std::is_same_v<T, i128>) {
      if (std::max<T>((n < 0 ? -n : n), d) > std::numeric_limits<i64>::max()) {
        throw std::overflow_error("cannot fit in 64 bits");
      }
    }
    return true;
  }

  void reduce_me_() const {
    reduce_<i64>(nume_, deno_);
    reduced_ = true;
  }
};
using Rat = LazyRational;

template<class T>
T ceil_div(T x, T y) {
  assert(y != 0);
  return x / y + (((x ^ y) >= 0) and (x % y));
}

using namespace std;

auto solve() -> Int {
  int p = in, q = in, a = in, n = in;
  if (p == 0 and q == 0 and a == 0 and n == 0) {
    exit_();
  }

  auto f = Rec([&](auto &rec, int i, const Rat &r, Int d0, Int prod) -> Int {
    if (r.nume_ == 0) return 1;
    if (i == 0) return 0;
    Int res = 0;
    for (Int d = max<Int>(d0, ceil_div(r.deno_, r.nume_)); prod * d <= a; ++d) {
      res += rec(i - 1, r - Rat(1LL, d), d, prod * d);
    }
    return res;
  });
  return f(n, Rat(p, q), 1, 1);
}

int main() {
  init_();
  for (int t = 0;; ++t) {
    test_case(t, 0);
    out(solve());
  }
}
accuracy: 1
time_ms: 500
memory_kb: 3252
final_rank: 15

code_snippet: // #define NDEBUG
#include <bits/stdc++.h>

#define REP_(i, a_, b_, a, b, ...) for (int i = (a), END_##i = (b); i < END_##i; ++i)
#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define ALL(x) std::begin(x), std::end(x)
using Int = long long;
using Uint = unsigned long long;
using Real = long double;

template<typename T, typename U>
inline bool chmax(T &a, U b) { return a < b and ((a = b), true); }
template<typename T, typename U>
inline bool chmin(T &a, U b) { return a > b and ((a = b), true); }
template<typename T>
constexpr T kBig = std::numeric_limits<T>::max() / 2;
#if __cplusplus < 202002L
template<typename T>
inline int ssize(const T &a) { return (int) a.size(); }
#endif

struct CastInput {
  template<typename T>
  operator T() const {
    T x;
    std::cin >> x;
    assert(bool(std::cin));
    return x;
  }
  struct Sized {
    int n;
    template<typename T>
    operator T() const {
      T xs(n);
      for (auto &x: xs) {
        std::cin >> x;
        assert(bool(std::cin));
      }
      return xs;
    }
  };
  Sized operator()(int n) const { return {n}; }
} in;

template<typename Container>
std::ostream &out_seq(const Container &seq, const char *sep = " ",
                      const char *ends = "\n", std::ostream &os = std::cout) {
  const auto itl = std::begin(seq), itr = std::end(seq);
  for (auto it = itl; it != itr; ++it) {
    if (it != itl) os << sep;
    os << *it;
  }
  return os << ends;
}

template<typename T>
std::ostream &out_one(const T &x, char endc) {
  if constexpr (std::is_same<T, bool>::value) {
    return std::cout << (x ? "Yes" : "No") << endc;
  } else {
    return std::cout << x << endc;
  }
}
template<typename T>
std::ostream &out(const T &x) {
  return out_one(x, '\n');
}
template<typename T, typename... Ts>
std::ostream &out(const T &head, Ts... tail) {
  return out_one(head, ' '), out(tail...);
}

void init_(bool interactive = false) {
  std::ios::sync_with_stdio(false);
  if (not interactive) std::cin.tie(nullptr);
  std::cout << std::fixed << std::setprecision(18);
}

[[noreturn]] void exit_() {
#ifdef MY_DEBUG
  std::string _;
  assert((std::cin >> _).fail());
#endif
  std::cout.flush(), std::cerr.flush(), std::_Exit(0);
}

#ifdef MY_DEBUG
#include "debug_dump.hpp"
#include "backward.hpp"
backward::SignalHandling kSignalHandling;
#else
#define DUMP(...)
#define test_case(...)
#define cerr if(false)cerr
#endif

template<class F>
struct Rec {
  F f_;
  explicit Rec(F f) : f_(std::move(f)) {}
  template<class... Args>
  decltype(auto) operator()(Args &&... args) {
    return f_(*this, std::forward<Args>(args)...);
  }
};
template<class F> Rec(F) -> Rec<F>;

// Rational number with lazy reduction.
struct LazyRational {
  using i64 = long long;
  using i128 = __int128_t;

  mutable i64 nume_;
  mutable i64 deno_;
  mutable bool reduced_;

  static constexpr i64 kReduceThreshold = i64(1) << 62;

  LazyRational() : nume_(0), deno_(1), reduced_(true) {}
  LazyRational(i64 n) : nume_(n), deno_(1), reduced_(true) {}

  LazyRational(i128 n, i128 d) : reduced_(false) {
    assert(d != 0);  // zero division
    if (n == 0) {
      d = 1;
      reduced_ = true;
    } else {
      const int sign = ((n < 0) xor (d < 0)) ? -1 : 1;
      if (n < 0) n = -n;
      if (d < 0) d = -n;
      if (std::max<i128>(n, d) > kReduceThreshold) {
        reduce_(n, d);
      }
      n *= sign;
    }
    nume_ = (i64) n;
    deno_ = (i64) d;
  }

  i64 numerator() const {
    if (not reduced_) reduce_me_();
    return nume_;
  }

  i64 denominator() const {
    if (not reduced_) reduce_me_();
    return deno_;
  }

  // Cast to a floating point number.
  template<typename Float>
  explicit operator Float() const {
    static_assert(std::is_floating_point<Float>::value);
    return (Float) nume_ / (Float) deno_;
  }

  const LazyRational &operator+() const { return *this; }

  LazyRational operator-() const {
    LazyRational ret;
    ret.nume_ = -this->nume_;
    ret.deno_ = this->deno_;
    ret.reduced_ = this->reduced_;
    return ret;
  }

  friend bool operator==(const LazyRational &x, const LazyRational &y) {
    return i128(x.nume_) * y.deno_ == i128(x.deno_) * y.nume_;
  }
  friend bool operator!=(const LazyRational &x, const LazyRational &y) {
    return not(x == y);
  }
  friend bool operator<(const LazyRational &x, const LazyRational &y) {
    return i128(x.nume_) * y.deno_ < i128(x.deno_) * y.nume_;
  }
  friend bool operator>(const LazyRational &x, const LazyRational &y) { return y < x; }
  friend bool operator<=(const LazyRational &x, const LazyRational &y) {
    return not(x > y);
  }
  friend bool operator>=(const LazyRational &x, const LazyRational &y) {
    return not(x < y);
  }

  LazyRational &operator+=(const LazyRational &y) {
    i128 zn = i128(this->nume_) * y.deno_ + i128(y.nume_) * this->deno_;
    i128 zd = i128(this->deno_) * y.deno_;
    this->reduced_ = light_reduce_(zn, zd);
    this->nume_ = zn;
    this->deno_ = zd;
    return *this;
  }
  friend LazyRational operator+(LazyRational x, const LazyRational &y) {
    x += y;
    return x;
  }

  friend LazyRational operator-(const LazyRational &x, const LazyRational &y) {
    return x + (-y);
  }
  LazyRational &operator-=(const LazyRational &y) {
    *this += -y;
    return *this;
  }

  LazyRational &operator*=(const LazyRational &y) {
    if (this->nume_ == 0) return *this;
    if (y.nume_ == 0) {
      this->nume_ = 0;
      this->deno_ = 1;
      this->reduced_ = true;
      return *this;
    }
    i128 zn = i128(this->nume_) * y.nume_;
    i128 zd = i128(this->deno_) * y.deno_;
    this->reduced_ = light_reduce_(zn, zd);
    this->nume_ = zn;
    this->deno_ = zd;
    return *this;
  }
  friend LazyRational operator*(LazyRational x, const LazyRational &y) {
    x *= y;
    return x;
  }

  LazyRational inv() const {
    LazyRational ret;
    int sign = this->nume_ >= 0 ? 1 : -1;
    ret.nume_ = this->deno_ * sign;
    ret.deno_ = this->nume_ * sign;
    ret.reduced_ = this->reduced_;
    return ret;
  }
  friend LazyRational operator/(const LazyRational &x, const LazyRational &y) {
    return x * y.inv();
  }
  LazyRational &operator/=(const LazyRational &y) {
    *this *= y.inv();
    return *this;
  }

  friend std::ostream &operator<<(std::ostream &os, const LazyRational &x) {
    return os << x.numerator() << "/" << x.denominator();
  }

 private:
  template<typename T>
  static void reduce_(T &n, T &d) {
    if (n == 0) {
      d = 1;
      return;
    }
    i128 a = (n < 0 ? -n : n), b = d;
    while (b) {
      a %= b;
      std::swap(a, b);
    }
    n /= a;
    d /= a;
  }

  // Returns whether the args are reduced.
  template<typename T>
  static bool light_reduce_(T &n, T &d) {
    if (std::max<T>((n < 0 ? -n : n), d) <= kReduceThreshold) {
      return false;
    }
    reduce_(n, d);
    if constexpr (std::is_same_v<T, i128>) {
      if (std::max<T>((n < 0 ? -n : n), d) > std::numeric_limits<i64>::max()) {
        throw std::overflow_error("cannot fit in 64 bits");
      }
    }
    return true;
  }

  void reduce_me_() const {
    reduce_<i64>(nume_, deno_);
    reduced_ = true;
  }
};
using Rat = LazyRational;
// using Rat = Rational<multip::checked_int128_t>; // for testing overflow


template<class T>
T ceil_div(T x, T y) {
  assert(y != 0);
  return x / y + (((x ^ y) >= 0) and (x % y));
}

using namespace std;

auto solve() -> Int {
  int p = in, q = in, a = in, n = in;
  if (p == 0 and q == 0 and a == 0 and n == 0) {
    exit_();
  }

  auto f = Rec([&](auto &rec, int i, const Rat &r, Int d0, Int prod) -> Int {
    if (r.nume_ == 0) return 1;
    if (i == 0) return 0;
    Int res = 0;
    for (Int d = max<Int>(d0, ceil_div(r.deno_, r.nume_)); prod * d <= a; ++d) {
      res += rec(i - 1, r - Rat(1, d), d, prod * d);
    }
    return res;
  });
  return f(n, Rat(p, q), 1, 1);
}

int main() {
  init_();
  for (int t = 0;; ++t) {
    test_case(t, 0);
    out(solve());
  }
}
accuracy: 1
time_ms: 460
memory_kb: 3084
final_rank: 13

code_snippet: using namespace std;
#include "bits/stdc++.h"

// add your library with double quotation #include"" here.
//#include "atcoder/all"
//using namespace atcoder;

// define your macros here.
#define MOD 1000000007
#define PI 3.14159265358979323846264338327950288419
#define IINF 1001001001
#define LINF 1001001001001001001LL

#define ll long long
#define VLL vector<ll>
#define PLL pair<ll, ll>
#define pb push_back
#define mpair make_pair
#define pm(first, second) pb(mpair((first), (second)))
#define pff first.first
#define pfs first.second
#define psf second.first
#define pss second.second

#define REP(i,n) for(ll i = 0; i < (ll)(n); i++)
#define REPS(i, n) for(ll i = 1; i <= (ll)(n); i++)
#define RREP(i, n) for(int i = ((ll)(n)-1); i >= 0; i--)
#define RREPS(i, n) for(int i = ((ll)(n)); i > 0; i--)
#define FOR(i, a, b) for(ll i = (a); i < (b); i++)
#define SZ(x) ((ll)(x).size())
#define ALL(x) (x).begin(), (x).end()
#define RALL(x) (x).rbegin(), (x).rend()
#define MAX(a, b) max((ll)(a), (ll)(b))
#define MIN(a, b) min((ll)(a), (ll)(b))
#define DCEIL(a, b) (((a)+(b)-1)/(b))
#define UNIQUE(x) (x).erase(unique((x).begin(), (x).end()), (x).end())
#define outyn(flag) cout << ((flag)? "Yes": "No") << endl
#define outYN(flag) cout << ((flag)? "YES": "NO") << endl
#define out(output) cout << (output) << endl

template<class T>bool chmax(T &a, const T &b) { return a < b && (a = b, true); }
template<class T>bool chmin(T &a, const T &b) { return a > b && (a = b, true); }
ll qp(ll a, ll b){ll ans=1;do{if(b&1)ans=1LL*ans*a;a=1LL*a*a;}while(b>>=1);return ans;}
ll qp(ll a, ll b, ll mo){ll ans=1;do{if(b&1)ans=1LL*ans*a%mo;a=1LL*a*a%mo;}while(b>>=1);return ans;}
int DX[4] = {1, 0, -1, 0};
int DY[4] = {0, 1, 0, -1};

#define int long long

int p, q, a;

int calc(int n, int d, int prod, int sum){
    int cnt = 0;
    for(int i = d; prod*i <= a; i++){
        int l = p*(prod*i);
        int r = sum*i+prod;
        if(l < r*q) continue;
        if(l == r*q){
            cnt++;
            continue;
        }
        if(n == 1) continue;
        cnt += calc(n-1, i, prod*i, r);
    }
    return cnt;
}
void solve(){
    // write your solution here.

    int n;
    while(true){
        cin >> p >> q >> a >> n;
        if(p == 0 && q == 0 && a == 0 && n == 0) return;
        cout << calc(n, 1, 1, 0) << endl;
    }
    
}
#undef int

// generated by oj-template v4.7.2 (https://github.com/online-judge-tools/template-generator)
int main() {
    // Fasterize input/output script
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    //cout << fixed << setprecision(100);
    // scanf/printf user should delete this fasterize input/output script

    int t = 1;
    //cin >> t; // comment out if solving multi testcase
    for(int testCase = 1;testCase <= t;++testCase){
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3216
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define bokusunny ios::sync_with_stdio(false), cin.tie(nullptr);

// 有理数クラス
// 初期化 O(logN) (NOTE:重い場合、約分の必要がないのであればlogを取れる)
// 分母分子が両方とも0でない → マイナスは分子に寄せる&約分
// 分母が0 → 未定義
// 分子が0 → 分母は1で統一
struct Rational {
 private:
  long long NUM;   // numerator, 分子
  long long DENO;  // denominator, 分母

  void normalize() {
    if (NUM == 0) {
      DENO = 1;
    } else {
      // ---必要に応じてコメントアウトするとlogが落ちる---
      // auto g = gcd(NUM, DENO);
      // NUM /= g;
      // DENO /= g;
      // ------------------------------------------

      if (DENO < 0) {
        NUM *= -1;
        DENO *= -1;
      }
    }
  }

 public:
  Rational(long long num, long long deno) : NUM(num), DENO(deno) {
    normalize();
    // NOTE: num, deno共にintの範囲に収めないと、比較の際にオーバーフローする
    //       llを使いたい &&
    //       setやmapを使ってるだけの場合、unorderedに変えると比較演算子を使わないのでオーバーフローしない
    assert(NUM < INT_MAX);
    assert(DENO < INT_MAX);
  }
  Rational(long long &n) : NUM(n), DENO(1){};

  long long num() const { return NUM; }
  long long deno() const { return DENO; }
  double to_d() { return (double)NUM / DENO; }

  bool operator<(const Rational &b) const { return NUM * b.DENO < b.NUM * DENO; }
  bool operator>(const Rational &b) const { return NUM * b.DENO > b.NUM * DENO; }
  bool operator<=(const Rational &b) const { return NUM * b.DENO <= b.NUM * DENO; }
  bool operator>=(const Rational &b) const { return NUM * b.DENO >= b.NUM * DENO; }
  bool operator==(const Rational &b) const { return NUM == b.NUM && DENO == b.DENO; }
  bool operator!=(const Rational &b) const { return !(*this == b); }
  Rational operator+=(const Rational &x);
  Rational operator+=(long long x);
  Rational operator-=(const Rational &x);
  Rational operator-=(long long x);
  Rational operator*=(const Rational &x);
  Rational operator*=(long long x);
  Rational operator/=(const Rational &x);
  Rational operator/=(long long x);
};
inline Rational operator+(const Rational &a, const Rational &b) {
  long long num = a.num() * b.deno() + a.deno() * b.num();
  long long deno = a.deno() * b.deno();
  return Rational(num, deno);
}
inline Rational operator-(const Rational &a, const Rational &b) {
  long long num = a.num() * b.deno() - a.deno() * b.num();
  long long deno = a.deno() * b.deno();
  return Rational(num, deno);
}
inline Rational operator*(const Rational &a, const Rational &b) {
  long long num = a.num() * b.num();
  long long deno = a.deno() * b.deno();
  return Rational(num, deno);
}
inline Rational operator/(const Rational &a, const Rational &b) {
  long long num = a.num() * b.deno();
  long long deno = a.deno() * b.num();
  return Rational(num, deno);
}
inline Rational Rational::operator+=(const Rational &x) {
  *this = *this + x;
  return *this;
}
inline Rational Rational::operator+=(long long x) {
  *this = *this + Rational(x);
  return *this;
}
inline Rational Rational::operator-=(const Rational &x) {
  *this = *this - x;
  return *this;
}
inline Rational Rational::operator-=(long long x) {
  *this = *this - Rational(x);
  return *this;
}
inline Rational Rational::operator*=(const Rational &x) {
  *this = *this * x;
  return *this;
}
inline Rational Rational::operator*=(long long x) {
  *this = *this * Rational(x);
  return *this;
}
inline Rational Rational::operator/=(const Rational &x) {
  *this = *this / x;
  return *this;
}
inline Rational Rational::operator/=(long long x) {
  *this = *this / Rational(x);
  return *this;
}
inline ostream &operator<<(ostream &os, const Rational &f) {
  os << f.num();
  if (f.deno() != 1) os << "/" << f.deno();
  return os;
}

namespace std {
template <>
struct hash<Rational> {
  size_t operator()(const Rational &f) const {
    size_t seed = 0;
    // メンバ変数の数だけ行う
    auto num_hash = hash<long long>()(f.num());
    seed ^= num_hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    auto deno_hash = hash<long long>()(f.deno());
    seed ^= deno_hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);

    return seed;
  }
};
}  // namespace std

void solve(int p, int q, int a, int n) {
  auto dfs = [&](auto dfs, Rational cur, int mi_deno, int prod, int cnt) -> int {
    if (cur.num() == 0) return 1;
    if (cur.num() < 0) return 0;
    if (cnt >= n) return 0;

    int res = 0;
    for (int deno = mi_deno; deno * prod <= a; deno++) {
      res += dfs(dfs, cur - Rational(1, deno), deno, deno * prod, cnt + 1);
    }
    return res;
  };
  cout << dfs(dfs, Rational(p, q), 1, 1, 0) << endl;
}

int main() {
  bokusunny;
  int p, q, a, n;
  while (cin >> p >> q >> a >> n) {
    if (p == 0 && q == 0 && a == 0 && n == 0) break;
    solve(p, q, a, n);
  }

  return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 3220
final_rank: 6

code_snippet: #include<iostream>
#include<set>
#include<cmath>
using namespace std;
const double eps=1e-10;
set<multiset<int> >ans;
set<multiset<int> >processed;
int p,q,a,n;
void solve(multiset<int>now_solution,double remain,int product)
{
    //if(processed.find(now_solution)!=processed.end())
    //    return;
    if(abs(remain)<eps)
    {
        ans.insert(now_solution);
        return;
    }
    //for(int i=1;product*i<=a&&
    //(int)now_solution.size()+1<=n;++i)
    int nowstep=(int)now_solution.size();
    for(int i=a/product;
    nowstep+1<=n
    &&(remain-(double)1/i>0||abs(remain-(double)1/i)<eps);
    --i)
    {
        double max_remain=remain-(double)(n-nowstep)*1/i;
        if(max_remain>0&&abs(max_remain)>eps)
            continue;
        multiset<int>new_solution=now_solution;
        new_solution.insert(i);
        solve(new_solution,remain-(double)1/i,product*i);
    }
    //processed.insert(now_solution);
}
int main()
{
    while(scanf("%d%d%d%d",&p,&q,&a,&n),p||q||a||n)
    {
        ans.clear();
        processed.clear();
        multiset<int>tmp;
        solve(tmp,(double)p/q,1);
        printf("%d\n",(int)ans.size());
    }
}
//293 144 6748 7
accuracy: 1
time_ms: 360
memory_kb: 3332
final_rank: 14

code_snippet: #line 1 "fractional.test.cpp"
#define PROBLEM \
  "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1131&lang=jp"

#line 2 "/home/arc/project/comppro/cplib/math/fractional.cpp"

#include <cmath>
#include <ostream>

#line 2 "/home/arc/project/comppro/cplib/math/gcd.cpp"
#include <cstdint>
#include <utility>

int64_t GCD(int64_t a, int64_t b) {
    if (a < b)
        std::swap(a, b);
    int r;
    while (1) {
        r = a % b;
        if (r == 0) {
            return b;
        } else {
            a = b;
            b = r;
        }
    }
}
#line 7 "/home/arc/project/comppro/cplib/math/fractional.cpp"
/**
 * @brief 有理数 p/qを表すライブラリ
 *
 */
struct Fractional {
  int64_t p, q;

  /**
   * @brief pが負になるようにして通分する
   *
   * @return Fractional
   */
  Fractional normalize() noexcept {
    if (p == 0) {
      q = 1;
      return *this;
    }

    if (q < 0) {
      p *= -1;
      q *= -1;
    }
    // int64_t gcd = GCD(abs(p), abs(q));
    // p /= gcd;
    // q /= gcd;
    return *this;
  }

  Fractional() = default;
  Fractional(int64_t _p, int64_t _q = 1) : p(_p), q(_q) {
    normalize();
  }

  inline long double toDouble() const {
    return (long double)p / q;
  }

  inline Fractional operator-() const {
    return Fractional(-p, q);
  }

  inline Fractional& operator+=(const Fractional& f) {
    int64_t np = p * f.q + q * f.p, nq = q * f.q;
    p = np;
    q = nq;
    normalize();
    return *this;
  }

  inline Fractional& operator-=(const Fractional& f) {
    int64_t np = p * f.q - q * f.p, nq = q * f.q;
    p = np;
    q = nq;
    normalize();
    return *this;
  }

  inline Fractional& operator*=(const Fractional& f) {
    p *= f.p;
    q *= f.q;
    normalize();
    return *this;
  }

  inline Fractional& operator/=(const Fractional& f) {
    p *= f.q;
    q *= f.p;
    normalize();
    return *this;
  }

  inline friend std::ostream& operator<<(std::ostream& stream,
                                         const Fractional& f) {
    stream << f.p << "/" << f.q;
    return stream;
  }
};

inline Fractional operator+(const Fractional& a, const Fractional& b) {
  return Fractional(a) += b;
}

inline Fractional operator-(const Fractional& a, const Fractional& b) {
  return Fractional(a) -= b;
}

inline Fractional operator*(const Fractional& a, const Fractional& b) {
  return Fractional(a) *= b;
}

inline Fractional operator/(const Fractional& a, const Fractional& b) {
  return Fractional(a) /= b;
}

inline bool operator==(const Fractional& a, const Fractional& b) {
  return a.p * b.q == a.q * b.p;
}

inline bool operator!=(const Fractional& a, const Fractional& b) {
  return !(a == b);
}

inline bool operator<(const Fractional& a, const Fractional& b) {
  return a.p * b.q < a.q * b.p;
}

inline bool operator>(const Fractional& a, const Fractional& b) {
  return b < a;
}

inline bool operator<=(const Fractional& a, const Fractional& b) {
  return a.p * b.q <= a.q * b.p;
}

inline bool operator>=(const Fractional& a, const Fractional& b) {
  return b <= a;
}
#line 5 "fractional.test.cpp"

#include <iostream>

using namespace std;

int solve(Fractional frac, int a, int product, int n, int start) {
  if (frac == Fractional(0, 1)) {
    return 1;
  }
  if (n == 0) {
    return 0;
  }

  int res = 0;
  for (int v = start; v <= a; v++) {
    if (product * v > a) break;
    Fractional f(1, v);
    Fractional remain = frac - f;
    if (remain < Fractional(0, 1)) continue;
    res += solve(remain, a, product * v, n - 1, v);
  }
  return res;
}

int main(void) {
  while (true) {
    int p, q, a, n;
    cin >> p >> q >> a >> n;
    if (p == 0) break;
    cout << solve(Fractional(p, q), a, 1, n, 1) << endl;
  }
}
accuracy: 1
time_ms: 120
memory_kb: 3200
final_rank: 5

code_snippet: #include <iostream>

template <typename T> class Rational {
    T num, den;

    static T my_gcd(T x_, T y_) {
        unsigned long long x = x_ < 0 ? -x_ : x_, y = y_ < 0 ? -y_ : y_;
        if (!x or !y) return x + y;
        int n = __builtin_ctzll(x), m = __builtin_ctzll(y);
        x >>= n, y >>= m;
        while (x != y) {
            if (x > y)
                x = (x - y) >> __builtin_ctzll(x - y);
            else
                y = (y - x) >> __builtin_ctzll(y - x);
        }
        return x << (n > m ? m : n);
    }

    void normalize() {
        return;  // comment out this flexibly
        T g = my_gcd(num, den);
        num /= g, den /= g;
        if (den < 0) num = -num, den = -den;
    }

public:
    Rational() {}
    Rational(T num) : num(num), den(T(1)) {}
    Rational(T num, T den) : num(num), den(den) { normalize(); }

    Rational operator+(const Rational& r) const { return Rational(num * r.den + den * r.num, den * r.den); }
    Rational operator-(const Rational& r) const { return Rational(num * r.den - den * r.num, den * r.den); }
    Rational operator*(const Rational& r) const { return Rational(num * r.num, den * r.den); }
    Rational operator/(const Rational& r) const { return Rational(num * r.den, den * r.num); }
    Rational& operator+=(const Rational& r) { return *this = *this + r; }
    Rational& operator-=(const Rational& r) { return *this = *this - r; }
    Rational& operator*=(const Rational& r) { return *this = *this * r; }
    Rational& operator/=(const Rational& r) { return *this = *this / r; }

    Rational operator+(const T& val) const { return *this + Rational(val); }
    Rational operator-(const T& val) const { return *this - Rational(val); }
    Rational operator*(const T& val) const { return *this * Rational(val); }
    Rational operator/(const T& val) const { return *this / Rational(val); }
    Rational& operator+=(const T& val) { return *this = *this + val; }
    Rational& operator-=(const T& val) { return *this = *this - val; }
    Rational& operator*=(const T& val) { return *this = *this * val; }
    Rational& operator/=(const T& val) { return *this = *this / val; }
    friend Rational operator+(const T& val, const Rational& r) { return r + val; }
    friend Rational operator-(const T& val, const Rational& r) { return r - val; }
    friend Rational operator*(const T& val, const Rational& r) { return r * val; }
    friend Rational operator/(const T& val, const Rational& r) { return r / val; }

    Rational operator-() const { return Rational(-num, den); }
    Rational abs() const { return Rational(num < 0 ? -num : num, den); }

    bool operator==(const Rational& r) const {
        if (den == 0 and r.den == 0) return num == r.num;
        if (den == 0 or r.den == 0) return false;
        return num * r.den == den * r.num;
    }
    bool operator!=(const Rational& r) const { return !(*this == r); }
    bool operator<(const Rational& r) const {
        if (den == 0 and r.den == 0) return num < r.num;
        if (den == 0) return num < 0;
        if (r.den == 0) return r.num > 0;
        return num * r.den < den * r.num;
    }
    bool operator<=(const Rational& r) const { return (*this == r) or (*this < r); }
    bool operator>(const Rational& r) const { return r < *this; }
    bool operator>=(const Rational& r) const { return (*this == r) or (*this > r); }

    bool operator==(const T& val) const { return *this == Rational(val); }
    bool operator!=(const T& val) const { return *this != Rational(val); }
    bool operator<(const T& val) const { return *this < Rational(val); }
    bool operator<=(const T& val) const { return *this <= Rational(val); }
    bool operator>(const T& val) const { return *this > Rational(val); }
    bool operator>=(const T& val) const { return *this >= Rational(val); }
    friend bool operator==(const T& val, const Rational& r) { return r == val; }
    friend bool operator!=(const T& val, const Rational& r) { return r != val; }
    friend bool operator<(const T& val, const Rational& r) { return r > val; }
    friend bool operator<=(const T& val, const Rational& r) { return r >= val; }
    friend bool operator>(const T& val, const Rational& r) { return r < val; }
    friend bool operator>=(const T& val, const Rational& r) { return r <= val; }

    explicit operator double() const { return (double)num / (double)den; }
    explicit operator long double() const { return (long double)num / (long double)den; }
    friend std::ostream& operator<<(std::ostream& os, const Rational& r) { return os << r.num << '/' << r.den; }
};

/**
 * @brief Rational Number
 * @docs docs/util/Rational.md
 */

using R = Rational<int>;

int dfs(R r, int dep, int pre, int mul, int a) {
    if (dep == 0) return r == 0;
    if (r == 0) return 1;
    int res = 0;
    for (int i = a / mul; i >= pre; i--) {
        if (r < R(1, i)) break;
        res += dfs(r - R(1, i), dep - 1, i, mul * i, a);
    }
    return res;
}

void solve(int p, int q, int a, int n) {
    R r(p, q);
    int ans = dfs(r, n, 1, 1, a);
    std::cout << ans << '\n';
}

int main() {
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    for (int p, q, a, n; std::cin >> p >> q >> a >> n, n;) solve(p, q, a, n);
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 3376
final_rank: 11

code_snippet: #include <iostream>

template <typename T> class Rational {
    T num, den;

    // static T my_gcd(T x_, T y_) {
    //     unsigned long long x = x_ < 0 ? -x_ : x_, y = y_ < 0 ? -y_ : y_;
    //     if (!x or !y) return x + y;
    //     int n = __builtin_ctzll(x), m = __builtin_ctzll(y);
    //     x >>= n, y >>= m;
    //     while (x != y) {
    //         if (x > y)
    //             x = (x - y) >> __builtin_ctzll(x - y);
    //         else
    //             y = (y - x) >> __builtin_ctzll(y - x);
    //     }
    //     return x << (n > m ? m : n);
    // }

    static T my_gcd(T a, T b) {
        if (a < 0) a = -a;
        if (b < 0) b = -b;
        while (a and b) {
            if (a > b)
                a %= b;
            else
                b %= a;
        }
        return a + b;
    }

    void normalize() {
        return;
        T g = my_gcd(num, den);
        num /= g, den /= g;
        if (den < 0) num = -num, den = -den;
    }

public:
    Rational() {}
    Rational(T num) : num(num), den(T(1)) {}
    Rational(T num, T den) : num(num), den(den) { normalize(); }

    Rational operator+(const Rational& r) const { return Rational(num * r.den + den * r.num, den * r.den); }
    Rational operator-(const Rational& r) const { return Rational(num * r.den - den * r.num, den * r.den); }
    Rational operator*(const Rational& r) const { return Rational(num * r.num, den * r.den); }
    Rational operator/(const Rational& r) const { return Rational(num * r.den, den * r.num); }
    Rational& operator+=(const Rational& r) { return *this = *this + r; }
    Rational& operator-=(const Rational& r) { return *this = *this - r; }
    Rational& operator*=(const Rational& r) { return *this = *this * r; }
    Rational& operator/=(const Rational& r) { return *this = *this / r; }

    Rational operator+(const T& val) const { return *this + Rational(val); }
    Rational operator-(const T& val) const { return *this - Rational(val); }
    Rational operator*(const T& val) const { return *this * Rational(val); }
    Rational operator/(const T& val) const { return *this / Rational(val); }
    Rational& operator+=(const T& val) { return *this = *this + val; }
    Rational& operator-=(const T& val) { return *this = *this - val; }
    Rational& operator*=(const T& val) { return *this = *this * val; }
    Rational& operator/=(const T& val) { return *this = *this / val; }
    friend Rational operator+(const T& val, const Rational& r) { return r + val; }
    friend Rational operator-(const T& val, const Rational& r) { return r - val; }
    friend Rational operator*(const T& val, const Rational& r) { return r * val; }
    friend Rational operator/(const T& val, const Rational& r) { return r / val; }

    Rational operator-() const { return Rational(-num, den); }
    Rational abs() const { return Rational(num < 0 ? -num : num, den); }

    bool operator==(const Rational& r) const {
        if (den == 0 and r.den == 0) return num == r.num;
        if (den == 0 or r.den == 0) return false;
        return num * r.den == den * r.num;
    }
    bool operator!=(const Rational& r) const { return !(*this == r); }
    bool operator<(const Rational& r) const {
        if (den == 0 and r.den == 0) return num < r.num;
        if (den == 0) return num < 0;
        if (r.den == 0) return r.num > 0;
        return num * r.den < den * r.num;
    }
    bool operator<=(const Rational& r) const { return (*this == r) or (*this < r); }
    bool operator>(const Rational& r) const { return r < *this; }
    bool operator>=(const Rational& r) const { return (*this == r) or (*this > r); }

    bool operator==(const T& val) const { return *this == Rational(val); }
    bool operator!=(const T& val) const { return *this != Rational(val); }
    bool operator<(const T& val) const { return *this < Rational(val); }
    bool operator<=(const T& val) const { return *this <= Rational(val); }
    bool operator>(const T& val) const { return *this > Rational(val); }
    bool operator>=(const T& val) const { return *this >= Rational(val); }
    friend bool operator==(const T& val, const Rational& r) { return r == val; }
    friend bool operator!=(const T& val, const Rational& r) { return r != val; }
    friend bool operator<(const T& val, const Rational& r) { return r > val; }
    friend bool operator<=(const T& val, const Rational& r) { return r >= val; }
    friend bool operator>(const T& val, const Rational& r) { return r < val; }
    friend bool operator>=(const T& val, const Rational& r) { return r <= val; }

    explicit operator double() const { return (double)num / (double)den; }
    explicit operator long double() const { return (long double)num / (long double)den; }
    friend std::ostream& operator<<(std::ostream& os, const Rational& r) { return os << r.num << '/' << r.den; }
};

/**
 * @brief Rational Number
 * @docs docs/util/Rational.md
 */

using R = Rational<int>;

int dfs(R r, int dep, int pre, int mul, int a) {
    if (dep == 0) return r == 0;
    if (r == 0) return 1;
    int res = 0;
    for (int i = a / mul; i >= pre; i--) {
        if (r < R(1, i)) break;
        res += dfs(r - R(1, i), dep - 1, i, mul * i, a);
    }
    return res;
}

void solve(int p, int q, int a, int n) {
    R r(p, q);
    int ans = dfs(r, n, 1, 1, a);
    std::cout << ans << '\n';
}

int main() {
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    for (int p, q, a, n; std::cin >> p >> q >> a >> n, n;) solve(p, q, a, n);
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 3456
final_rank: 12

code_snippet: #include <iostream>

template <typename T> class Rational {
    T num, den;

    static T my_gcd(T x_, T y_) {
        unsigned long long x = x_ < 0 ? -x_ : x_, y = y_ < 0 ? -y_ : y_;
        if (!x or !y) return x + y;
        int n = __builtin_ctzll(x), m = __builtin_ctzll(y);
        x >>= n, y >>= m;
        while (x != y) {
            if (x > y)
                x = (x - y) >> __builtin_ctzll(x - y);
            else
                y = (y - x) >> __builtin_ctzll(y - x);
        }
        return x << (n > m ? m : n);
    }

    void normalize() {
        return;
        T g = my_gcd(num, den);
        num /= g, den /= g;
        if (den < 0) num = -num, den = -den;
    }

public:
    Rational() {}
    Rational(T num) : num(num), den(T(1)) {}
    Rational(T num, T den) : num(num), den(den) { normalize(); }

    Rational operator+(const Rational& r) const { return Rational(num * r.den + den * r.num, den * r.den); }
    Rational operator-(const Rational& r) const { return Rational(num * r.den - den * r.num, den * r.den); }
    Rational operator*(const Rational& r) const { return Rational(num * r.num, den * r.den); }
    Rational operator/(const Rational& r) const { return Rational(num * r.den, den * r.num); }
    Rational& operator+=(const Rational& r) { return *this = *this + r; }
    Rational& operator-=(const Rational& r) { return *this = *this - r; }
    Rational& operator*=(const Rational& r) { return *this = *this * r; }
    Rational& operator/=(const Rational& r) { return *this = *this / r; }

    Rational operator+(const T& val) const { return *this + Rational(val); }
    Rational operator-(const T& val) const { return *this - Rational(val); }
    Rational operator*(const T& val) const { return *this * Rational(val); }
    Rational operator/(const T& val) const { return *this / Rational(val); }
    Rational& operator+=(const T& val) { return *this = *this + val; }
    Rational& operator-=(const T& val) { return *this = *this - val; }
    Rational& operator*=(const T& val) { return *this = *this * val; }
    Rational& operator/=(const T& val) { return *this = *this / val; }
    friend Rational operator+(const T& val, const Rational& r) { return r + val; }
    friend Rational operator-(const T& val, const Rational& r) { return r - val; }
    friend Rational operator*(const T& val, const Rational& r) { return r * val; }
    friend Rational operator/(const T& val, const Rational& r) { return r / val; }

    Rational operator-() const { return Rational(-num, den); }
    Rational abs() const { return Rational(num < 0 ? -num : num, den); }

    bool operator==(const Rational& r) const {
        if (den == 0 and r.den == 0) return num == r.num;
        if (den == 0 or r.den == 0) return false;
        return num * r.den == den * r.num;
    }
    bool operator!=(const Rational& r) const { return !(*this == r); }
    bool operator<(const Rational& r) const {
        if (den == 0 and r.den == 0) return num < r.num;
        if (den == 0) return num < 0;
        if (r.den == 0) return r.num > 0;
        return num * r.den < den * r.num;
    }
    bool operator<=(const Rational& r) const { return (*this == r) or (*this < r); }
    bool operator>(const Rational& r) const { return r < *this; }
    bool operator>=(const Rational& r) const { return (*this == r) or (*this > r); }

    bool operator==(const T& val) const { return *this == Rational(val); }
    bool operator!=(const T& val) const { return *this != Rational(val); }
    bool operator<(const T& val) const { return *this < Rational(val); }
    bool operator<=(const T& val) const { return *this <= Rational(val); }
    bool operator>(const T& val) const { return *this > Rational(val); }
    bool operator>=(const T& val) const { return *this >= Rational(val); }
    friend bool operator==(const T& val, const Rational& r) { return r == val; }
    friend bool operator!=(const T& val, const Rational& r) { return r != val; }
    friend bool operator<(const T& val, const Rational& r) { return r > val; }
    friend bool operator<=(const T& val, const Rational& r) { return r >= val; }
    friend bool operator>(const T& val, const Rational& r) { return r < val; }
    friend bool operator>=(const T& val, const Rational& r) { return r <= val; }

    explicit operator double() const { return (double)num / (double)den; }
    explicit operator long double() const { return (long double)num / (long double)den; }
    friend std::ostream& operator<<(std::ostream& os, const Rational& r) { return os << r.num << '/' << r.den; }
};

/**
 * @brief Rational Number
 * @docs docs/util/Rational.md
 */

using R = Rational<int>;

int dfs(R r, int dep, int pre, int mul, int a) {
    if (dep == 0) return r == 0;
    if (r == 0) return 1;
    int res = 0;
    for (int i = a / mul; i >= pre; i--) {
        if (r < R(1, i)) break;
        res += dfs(r - R(1, i), dep - 1, i, mul * i, a);
    }
    return res;
}

void solve(int p, int q, int a, int n) {
    R r(p, q);
    int ans = dfs(r, n, 1, 1, a);
    std::cout << ans << '\n';
}

int main() {
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    for (int p, q, a, n; std::cin >> p >> q >> a >> n, n;) solve(p, q, a, n);
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 3308
final_rank: 10

code_snippet: #include <iostream>

using namespace std;

int p, q, a, n, ans;

void func(int numer, int denom, int pre, int mlt, int count)
{
	if (p * denom == q * numer) {
		ans++;
		return;
	}

	if (n == count) return;
	if (q * numer > p * denom) return;

	for (int i = pre; mlt * i < a + 1; i++) func(numer * i + denom, denom * i, i, mlt * i, count + 1);
}

int main()
{
	while (cin >> p >> q >> a >> n) {
		if (!p && !q && !a && !n) break;
		ans = 0;
		func(0, 1, 1, 1, 0);
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 90
memory_kb: 3364
final_rank: 8

code_snippet: #include <iostream>

using namespace std;

int p, q, a, n, ans;

void func(int numer, int denom, int pre, int mlt, int count)
{
	if (p * denom == q * numer) {
		ans++;
		return;
	}

	if (n == count) return;
	//if (q * numer > p * denom) return;

	for (int i = pre; mlt * i < a + 1; i++) func(numer * i + denom, denom * i, i, mlt * i, count + 1);
}

int main()
{
	while (cin >> p >> q >> a >> n) {
		if (!p && !q && !a && !n) break;
		ans = 0;
		func(0, 1, 1, 1, 0);
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 430
memory_kb: 3360
final_rank: 16

code_snippet: #include <iostream>
using namespace std;

int a;

int dfs(int p, int q, int seki, int bunbo, int n){
    
    if(p == 0 && n >= 0) return 1;
    if(n == 0) return 0;
    
    int res = 0;
    for(int i=bunbo; seki*i <= a; i++){
        int np = p*i-q;
        int nq = q*i;
        if(np < 0) continue;
        res += dfs(np, nq, seki*i, i, n-1);
    }
    
    return res;
}

int main()
{
    int p, q, n;
    while(cin >> p >> q >> a >> n, p!=0){
        cout << dfs(p, q, 1, 1, n) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 3008
final_rank: 1