Given a fraction in the form n/d, where gcd(n, d) = 1 and n ≤ d, find the largest possible fraction that is strictly less than n/d, also in reduced form (i.e., the numerator and denominator must be coprime), and where the numerator is less than or equal to the denominator.
Examples:
Input: n = 1, d = 8
Output: 1249 9993
Explanation: 1/8 >= 1249/9993 and this is the largest fraction.
Input: n = 2, d = 53
Output: 377 9991
Explanation: 2/53 >= 377/9991 and this is the largest fraction.
Input: n = 1, d = 1
Output: 9999 10000
Explanation: The constraints allow the maximum value of n or d to be 10^4.
1 ≤ n ≤ d ≤ 104
Table of Content
[Naive Approach] Try All Possible Numerator and Denominator Pairs - O(10 ^ 8 log(10 ^ 4)) Time and O(1) Auxiliary Space
The idea is to try all possible p/q where p <= q. Check if p/q < n/d and p and q are coprime. If it is larger than the current best fraction, update the answer. Finally, return the largest valid fraction.
Working of Approach:
- Try every possible numerator p and denominator q where p <= q.
- Check if p/q is strictly smaller than n/d using cross multiplication.
- If p and q are coprime, compare p/q with the best fraction found so far and update it.
- Finally, return the largest valid fraction found.
#include <iostream>
using namespace std;
// Function to find the largest fraction smaller than n/d.
vector<int> largestFraction(int n, int d)
{
int bestNum = 0;
int bestDen = 1;
// Try all possible numerators.
for (int p = 1; p <= 10000; p++)
{
// Try all possible denominators.
for (int q = p; q <= 10000; q++)
{
// Check if p/q is strictly smaller than n/d.
if (1LL * p * d < 1LL * n * q)
{
// Check if p/q is in reduced form.
if (__gcd(p, q) == 1)
{
// Check if p/q is greater than the best fraction.
if (1LL * p * bestDen > 1LL * bestNum * q)
{
bestNum = p;
bestDen = q;
}
}
}
}
}
return {bestNum, bestDen};
}
int main()
{
int n = 2;
int d = 53;
vector<int> ans = largestFraction(n, d);
cout << ans[0] << " " << ans[1] << endl;
return 0;
}
import java.util.Arrays;
public class GFG {
// Function to find the largest fraction smaller than
// n/d.
public static int[] largestFraction(int n, int d)
{
int bestNum = 0;
int bestDen = 1;
// Try all possible numerators.
for (int p = 1; p <= 10000; p++) {
// Try all possible denominators.
for (int q = p; q <= 10000; q++) {
// Check if p/q is strictly smaller than
// n/d.
if ((long)p * d < (long)n * q) {
// Check if p/q is in reduced form.
if (gcd(p, q) == 1) {
// Check if p/q is greater than the
// best fraction.
if ((long)p * bestDen
> (long)bestNum * q) {
bestNum = p;
bestDen = q;
}
}
}
}
}
return new int[] { bestNum, bestDen };
}
public static int gcd(int a, int b)
{
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
public static void main(String[] args)
{
int n = 2;
int d = 53;
int[] ans = largestFraction(n, d);
System.out.println(ans[0] + " " + ans[1]);
}
}
# Function to find the largest fraction smaller than n/d.
def largestFraction(n, d):
bestNum = 0
bestDen = 1
# Try all possible numerators.
for p in range(1, 10001):
# Try all possible denominators.
for q in range(p, 10001):
# Check if p/q is strictly smaller than n/d.
if p * d < n * q:
# Check if p/q is in reduced form.
if gcd(p, q) == 1:
# Check if p/q is greater than the best fraction.
if p * bestDen > bestNum * q:
bestNum = p
bestDen = q
return [bestNum, bestDen]
# Function to find GCD.
def gcd(a, b):
while b:
a, b = b, a % b
return a
if __name__ == '__main__':
n = 2
d = 53
ans = largestFraction(n, d)
print(ans[0], ans[1])
using System;
using System.Collections.Generic;
// Function to find the largest fraction smaller than n/d.
class GFG {
static int gcd(int a, int b)
{
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
return a;
}
public List<int> largestFraction(int n, int d)
{
int bestNum = 0;
int bestDen = 1;
// Try all possible numerators.
for (int p = 1; p <= 10000; p++) {
// Try all possible denominators.
for (int q = p; q <= 10000; q++) {
// Check if p/q is strictly smaller than
// n/d.
if ((long)p * d < (long)n * q) {
// Check if p/q is in reduced form.
if (gcd(p, q) == 1) {
// Check if p/q is greater than the
// best fraction.
if ((long)p * bestDen
> (long)bestNum * q) {
bestNum = p;
bestDen = q;
}
}
}
}
}
// Return the answer as a List.
return new List<int>{ bestNum, bestDen };
}
public static void Main()
{
int n = 2;
int d = 53;
GFG obj = new GFG();
List<int> ans = obj.largestFraction(n, d);
Console.WriteLine(ans[0] + " " + ans[1]);
}
}
function gcd(a, b)
{
if (b === 0) {
return a;
}
return gcd(b, a % b);
}
// Function to find the largest fraction smaller than n/d.
function largestFraction(n, d)
{
let bestNum = 0;
let bestDen = 1;
// Try all possible numerators.
for (let p = 1; p <= 10000; p++) {
// Try all possible denominators.
for (let q = p; q <= 10000; q++) {
// Check if p/q is strictly smaller than n/d.
if (p * d < n * q) {
// Check if p/q is in reduced form.
if (gcd(p, q) === 1) {
// Check if p/q is greater than the best
// fraction.
if (p * bestDen > bestNum * q) {
bestNum = p;
bestDen = q;
}
}
}
}
}
return [ bestNum, bestDen ];
}
// Driver Code
const n = 2;
const d = 53;
const ans = largestFraction(n, d);
console.log(ans[0] + " " + ans[1]);
Output
377 9991
[Expected Approach] Try All Possible Denominators - O(10 ^ 4) Time and O(1) Space
The idea is to try every possible denominator q from 10000 to 2. For each q, find the largest numerator p such that p/q < n/d. Then compare it with the best fraction found so far and finally reduce the answer using gcd.
Working of Approach:
- We try every possible denominator q from 10000 down to 2.
- For each q, we calculate the largest numerator p such that p/q < n/d.
- We compare the current fraction p/q with the best fraction r/s using cross multiplication.
- If p/q is larger, we update r and s.
- Finally, we use gcd to reduce r/s to its lowest form.
Let us understand with an example:
Input: n = 2, d = 53
- Initially, r = 0, s = 1, and limit = 10000.
- For each denominator q, calculate p = (2 * q - 1) / 53, the largest numerator making p/q < 2/53.
- For q = 9991, p = 377, giving the fraction 377/9991, which becomes the best fraction.
- After checking all denominators, the best fraction is 377/9991.
- gcd(377, 9991) = 1, so the final output is 377 9991.
#include <bits/stdc++.h>
using namespace std;
// Function to find the largest fraction smaller than n/d.
vector<int> largestFraction(int n, int d)
{
int r = 0, s = 1;
int limit = 10000;
// Try all possible denominators from 10000 down to 2.
for (int q = limit; q >= 2; q--)
{
// Find the largest numerator p such that p/q < n/d.
int p = (n * q - 1) / d;
// Check if the current fraction p/q is
// greater than or equal to the best fraction r/s.
if (p * s >= r * q)
{
// Update the best numerator and denominator.
r = p;
s = q;
}
}
// Find the GCD to reduce the fraction to its lowest form.
int D = __gcd(r, s);
vector<int> res;
// Store the reduced numerator.
res.push_back(r / D);
// Store the reduced denominator.
res.push_back(s / D);
return res;
}
int main()
{
int n = 2;
int d = 53;
// Find the largest fraction smaller than n/d.
vector<int> ans = largestFraction(n, d);
// Print the numerator and denominator.
cout << ans[0] << " " << ans[1] << endl;
return 0;
}
import java.util.Arrays;
public class GFG {
// Function to find the largest fraction smaller than
// n/d.
public static int[] largestFraction(int n, int d)
{
int r = 0, s = 1;
int limit = 10000;
// Try all possible denominators from 10000 down
// to 2.
for (int q = limit; q >= 2; q--) {
// Find the largest numerator p such that p/q <
// n/d.
int p = (n * q - 1) / d;
// Check if the current fraction p/q is
// greater than or equal to the best fraction
// r/s.
if (p * s >= r * q) {
// Update the best numerator and
// denominator.
r = p;
s = q;
}
}
// Find the GCD to reduce the fraction to its lowest
// form.
int D = gcd(r, s);
int[] res = new int[2];
// Store the reduced numerator.
res[0] = r / D;
// Store the reduced denominator.
res[1] = s / D;
return res;
}
public static int gcd(int a, int b)
{
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
public static void main(String[] args)
{
int n = 2;
int d = 53;
// Find the largest fraction smaller than n/d.
int[] ans = largestFraction(n, d);
// Print the numerator and denominator.
System.out.println(ans[0] + " " + ans[1]);
}
}
from math import gcd
# Function to find the largest fraction smaller than n/d.
def largestFraction(n, d):
r = 0
s = 1
limit = 10000
# Try all possible denominators from 10000 down to 2.
for q in range(limit, 1, -1):
# Find the largest numerator p such that p/q < n/d.
p = (n * q - 1) // d
# Check if the current fraction p/q is
# greater than or equal to the best fraction r/s.
if p * s >= r * q:
# Update the best numerator and denominator.
r = p
s = q
# Find the GCD to reduce the fraction to its lowest form.
D = gcd(r, s)
res = []
# Store the reduced numerator.
res.append(r // D)
# Store the reduced denominator.
res.append(s // D)
return res
if __name__ == "__main__":
n = 2
d = 53
# Find the largest fraction smaller than n/d.
ans = largestFraction(n, d)
# Print the numerator and denominator.
print(ans[0], ans[1])
using System;
using System.Collections.Generic;
// Function to find the largest fraction smaller than n/d.
class GFG {
// Function to find GCD.
static int gcd(int a, int b)
{
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
return a;
}
public List<int> largestFraction(int n, int d)
{
int r = 0, s = 1;
int limit = 10000;
// Try all possible denominators from 10000 down
// to 2.
for (int q = limit; q >= 2; q--) {
// Find the largest numerator p such that p/q <
// n/d.
int p = (n * q - 1) / d;
// Check if the current fraction p/q is
// greater than or equal to the best fraction
// r/s.
if ((long)p * s >= (long)r * q) {
// Update the best numerator and
// denominator.
r = p;
s = q;
}
}
// Find the GCD to reduce the fraction to its lowest
// form.
int D = gcd(r, s);
List<int> res = new List<int>();
// Store the reduced numerator.
res.Add(r / D);
// Store the reduced denominator.
res.Add(s / D);
return res;
}
public static void Main()
{
int n = 2;
int d = 53;
GFG obj = new GFG();
// Find the largest fraction smaller than n/d.
List<int> ans = obj.largestFraction(n, d);
// Print the numerator and denominator.
Console.WriteLine(ans[0] + " " + ans[1]);
}
}
function gcd(a, b)
{
if (b === 0) {
return a;
}
return gcd(b, a % b);
}
// Function to find the largest fraction smaller than n/d.
function largestFraction(n, d)
{
let r = 0, s = 1;
const limit = 10000;
// Try all possible denominators from 10000 down to 2.
for (let q = limit; q >= 2; q--) {
// Find the largest numerator p such that p/q < n/d.
let p = Math.floor((n * q - 1) / d);
// Check if the current fraction p/q is
// greater than or equal to the best fraction r/s.
if (p * s >= r * q) {
// Update the best numerator and denominator.
r = p;
s = q;
}
}
// Find the GCD to reduce the fraction to its lowest
// form.
const D = gcd(r, s);
const res = [];
// Store the reduced numerator.
res.push(Math.floor(r / D));
// Store the reduced denominator.
res.push(Math.floor(s / D));
return res;
}
// Driver Code
const n = 2;
const d = 53;
const ans = largestFraction(n, d);
console.log(ans.join(" "));
Output
377 9991