cppAcademy
FROM LEARNING TO COMPETING

Real problems.
Your next challenge.

Explore the Group C Olympiad archive.
Choose a topic. Find a challenge. Build your solution.

213 tasks across the Municipal, Regional, and National rounds (2009–2026), plus 4 previously featured problems. 146 tasks have independently written English summaries, analyses, and C++17 solutions; the remaining entries link to Arena. Topic tags are from Arena or our reviewed explanations. Difficulty labels are learning estimates, not official ratings.
GROUP C2011 · MediumExtended Euclid

Next Reduced Fraction

National Olympiad — National round

Submission name: fractions.cpp

Problem summary

List all reduced positive proper fractions with denominator at most z in increasing order. Given one member m/n and its following member p/q, determine p and q from z,m,n.

Input

z m n.

Output

Numerator p and denominator q of the following fraction.

Constraints

1≤z≤50,000,000; 1≤m<100,000; 2≤n<100,000. The fraction is a member of the stated sequence and a following member is assumed to exist.

Worked example

An independently prepared example for this explanation.

Input

8 1 3

Output

3 8

Solution analysis

  1. Consecutive Farey fractions satisfy n·p−m·q=1.
  2. Use the extended Euclidean algorithm to find the inverse of m modulo n; q must be congruent to its negative.
  3. Choose the largest such positive q≤z and compute p=(m·q+1)/n.

Why it works

The determinant equation gives a reduced fraction just above m/n. Choosing the largest allowed denominator ensures q+n>z. Any fraction strictly between these determinant-one neighbors has denominator at least n+q, so none is allowed.

Complexity: O(log n) time and space.

Watch out. Use 64-bit products. The task asks for the next fraction, not merely any larger reduced fraction.

Commented C++17 solution

An independently written complete program with standard headers.

// Key idea: The determinant equation gives a reduced fraction just above m/n. Choosing the largest
// allowed denominator ensures q+n>z.
#include<iostream>
using namespace std;
long long eg(long long a,long long b,long long&x,long long&y){
    if(!b){
        x=1;
        y=0;
        return a;
    }
    long long u,v,g=eg(b,a%b,u,v);
    x=v;
    y=u-(a/b)*v;
    return g;
}
int main(){
    long long z,m,n;
    cin>>z>>m>>n;
    long long x,y;
    eg(m,n,x,y);
    long long q=(-x%n+n)%n;
    if(!q){
        q=n;
    }
    q+=(z-q)/n*n;
    cout<<(m*q+1)/n<<' '<<q<<'\n';
}

Source: Arena Olimpiici ↗