Farey Sequence Problem
Difference between en1 and en2, changed 58 character(s)
First, the Farey sequence $F_n$ represents the set of all completely reduced proper fractions with denominators not exceeding $n$, arranged in ascending order of value. Formally speaking,↵

$$F_n = \left\{\frac{p}{q} \bigg\vert 0 < p < q \le n, \, \gcd(p, q) = 1\right\}$$↵

The asymptotic size of this sequence is $\sum\limits_{i = 1}^{n} \varphi(n) \sim \frac{3}{\pi^2}n^2 + o(n \log n)$.↵

Regarding the Farey sequence, there are two classic conclusions:↵

- If $\frac{a}{b}$ and $\frac{c}{d}$ are two consecutive elements in $F_n$, then $\frac{a + c}{b + d}$ is also a valid Farey fraction.↵

- If $\frac{a}{b}$ and $\frac{c}{d}$ are two consecutive elements in $F_n$, then their next element $\frac{p}{q}$ satisfies↵
$$\begin{cases}p = \left\lfloor\frac{n + b}{d}\right\rfloor c - a \\ q = \left\lfloor\frac{n + b}{d}\right\rfloor d - b\end{cases}$$↵

We will only prove the second theorem above. For the Farey sequence of order $n$, two adjacent terms $\frac{a}{b} < \frac{c}{d}$ satisfy $bc - ad = 1$. Since the adjacent terms $\frac{a}{b}, \, \frac{c}{d}$ are both on the Stern-Brocot tree, the next term $\frac{p}{q}$ satisfies $\frac{c}{d} = \frac{a + p}{b + q}$, which means $(p + a)d = (q + b)c$. Therefore, there exists $k$ such that↵

$$\begin{cases} kc = a + p \\ kd = b + q \end{cases}$$↵

To make $p, \, q$ highly precise (i.e., closely packed), the value of $k$ should be as large as possible. Therefore, concerning the upper bound $n$, $p, \, q$ are defined by the following equations:↵

$$\begin{cases}p = kc - a \le n \\ q = kd - b \le n\end{cases}$$↵

Obviously, from the definition of a proper fraction, we know $q > p$, so the maximum $k = \left\lfloor\frac{n + b}{d}\right\rfloor$, thus↵

$$\begin{cases}p = \left\lfloor\frac{n + b}{d}\right\rfloor c - a \\ q = \left\lfloor\frac{n + b}{d}\right\rfloor d - b\end{cases}$$↵

There are two computational methods to generate this sequence. The first one is based on the Stern-Brocot tree from the first theorem, which is very easy to implement.↵

```cpp↵
int build(int a, int b, int c, int d, int n) {↵
    if (b + d > n) return 0;↵
    return 1 + build(a, b, a + c, b + d, n) + build(a + c, b + d, c, d, n);↵
}↵
```↵

The other one is based on the recurrence from the second theorem, which is also quite easy to write.↵

```cpp↵
PII nxt_fraction(PII fac1, PII fac2) {↵
    auto [a, b] = fac1;↵
    auto [c, d] = fac2;↵
    return {(n + b) / d * c - a, (n + b) / d * d - b};↵
}↵
```↵

Obviously, they both use an $O(n^2)$ time complexity to compute specific elements of the Farey sequence.↵

To facilitate solving the parent problem, we present the following two problems:↵

> Given $n, \, k$, find the $k$-th term of $F_n$.↵

> Given $n$ and a completely reduced proper fraction $\frac{p}{q} (p \le n)$, determine its rank in $F_n$.↵

Let's consider the first problem first. We find that the first problem can be processed through the following steps:↵

- Binary search for $j$ in $\frac{j}{n}$, and calculate $\text{rank}(\frac{j}{n})$↵

- Let $r = \text{rank}(\frac{j}{n})$. If $r < k$, search upwards; otherwise, search downwards.↵

- Find an interval $\left[\frac{j}{n}, \, \frac{j + 1}{n}\right)$ such that the target fraction falls within this range.↵

- Count the fractions within this interval and find a valid fraction such that its rank equals the given $k$.↵

- Note that there is at most one fraction for each different denominator within this interval, because $\frac{1}{n}$ is the minimum spacing.↵

- For a fraction with a denominator $q$, the numerator of the only possible fraction can only be $\left\lfloor\frac{(j + 1)q - 1}{n}\right\rfloor$.↵

- Find the smallest fraction $\frac{p}{q}$ strictly greater than $\frac{j}{n}$, and use the recurrence from conclusion two until the given fraction reaches rank $k$.↵

We can see that problem one can be transformed into problem two to be implemented. Therefore, we now consider how to accomplish problem two.↵

More trivially, problem two can be reduced to the following problem:↵

> Given a real number $x$, find the number of completely reduced proper fractions $\frac{p}{q} \le x$ with denominators $q \le n$.↵

Let $A_q$ denote the number of completely reduced proper fractions with denominator $q$ that satisfy the above conditions. Obviously, the original problem can be expressed as finding such a set:↵

$$S = \left\{\frac{p}{q} \bigg\vert \frac{p}{q} \le x, \, q \le n, \, \gcd(p, \, q) = 1\right\}$$↵

That is, calculating $\sum\limits_{i = 1}^{n}A_i = |S|$, and we know that↵

$$\left\lfloor x \cdot q \right\rfloor = \sum\limits_{d \mid q}A_d$$↵

This tells us that↵

$$A_q = \left\lfloor x \cdot q \right\rfloor - \sum\limits_{d \mid q, \, d < q}A_d$$↵

We can simply compute this iteratively in ascending order. The complexity of each calculation is $O(n\log{n})$, making the complexity of problem one $O(n\log^2{n})$. Is there a more optimal approach?↵

Considering the essential form of $A_q$, by utilizing 
[Möbius inversion](https://www.cnblogs.com/YipChipqwq/p/18464696 "莫比乌斯反演"), we can obtain↵

$$A_q = \sum\limits_{i = 1}^{\lfloor x \cdot q \rfloor}[\gcd(i, q) = 1] = \sum\limits_{i = 1}^{\lfloor x \cdot q \rfloor}\sum\limits_{d \mid \gcd(i, q)}\mu(d)$$↵

If we sum up all $A_q$, then we have↵

$$\begin{aligned}↵
|S| &= \sum_{i = 1}^{n}A_i \\↵
&= \sum_{i = 1}^{n}\sum_{j = 1}^{\lfloor x \cdot i \rfloor}[\gcd(i, \, j) = 1] \\↵
&= \sum_{i = 1}^{n}\sum_{j = 1}^{\lfloor x \cdot i \rfloor}\sum_{d \mid \gcd(i, j)}\mu(d) \\↵
&= \sum_{d \mid i, \, d \mid j}\sum_{i = 1}^{n}\sum_{j = 1}^{\lfloor x \cdot i \rfloor}\mu(d) \\↵
&= \sum_{d = 1}^{n}\sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sum_{j = 1}^{\lfloor x \cdot i \rfloor}\mu(d) \\↵
&= \sum_{d = 1}^{n}\mu(d)\sum_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}\lfloor x \cdot i \rfloor↵
\end{aligned}$$↵

Consider setting $S(n) = \sum\limits_{i = 1}^{n}\lfloor x \cdot i \rfloor$, then what we equivalently need to calculate is↵

$$\sum_{d = 1}^{n}\mu(d)S\left(\left\lfloor\frac{n}{d}\right\rfloor\right)$$↵

By calculating the prefix sums of $\lfloor x \cdot i \rfloor$ and precomputing the Möbius function, we can solve this problem in $O(n)$ time complexity.↵

Thus, in solving Farey sequence problems, we have:↵

- Precomputation: $O(n)$↵

- Finding a fraction given its $\text{rank}$: $O(n\log{n})$↵

- Finding the $\text{rank}$ given a fraction: $O(n)$↵

- Finding the number of elements in $F_n$ smaller than a certain real number: $O(n)$↵

- Rational approximation of positive real numbers: $O(n\log{n})$↵

We provide a template code for reference.↵

```cpp↵
#include<bits/stdc++.h>↵
using namespace std;↵
#define ll long long↵
#define PII pair<ll, ll>↵
const int N = 2e6 + 10;↵
ll n;↵
ll primes[N], st[N], mu[N], cnt;↵

// precalculate Mu↵
void init_mu() {↵
    mu[1] = 1;↵
    for (int i = 2; i < N; i ++ ) {↵
        if (!st[i]) primes[cnt ++ ] = i, mu[i] = -1;↵
        for (int j = 0; i * primes[j] < N; j ++ ) {↵
            st[i * primes[j]] = 1;↵
            if (i % primes[j] == 0) break;↵
            mu[i * primes[j]] = -mu[i];↵
        }↵
    }↵
}↵

// O(n + logn) calculate next one by one↵
PII nxt_fraction(PII fac) {↵
    ll l = 0, r = n;↵
    while (l < r) {↵
        ll mid = l + r + 1 >> 1;↵
        if (mid * fac.second <= n * fac.first) l = mid;↵
        else r = mid - 1;↵
    }↵
    PII res = {r + 1, n};↵
    for (int i = 1; i <= n; i ++ ) {↵
        PII fac_i = {((r + 1) * i - 1) / n, i};↵
        if (fac_i.first * fac.second <= fac_i.second * fac.first) continue;↵
        if (fac_i.first * res.second < fac_i.second * res.first) res = fac_i;↵
    }↵
    ll d = __gcd(res.first, res.second);↵
    return {res.first / d, res.second / d};↵
}↵

// O(1) calculate next one by two nearly↵
PII nxt_fraction(PII fac1, PII fac2) {↵
    auto [a, b] = fac1;↵
    auto [c, d] = fac2;↵
    return {(n + b) / d * c - a, (n + b) / d * d - b};↵
}↵

ll fraction_to_rank(PII fac) {↵
    static ll A[N];↵
    for (int i = 1; i <= n; i ++ ) A[i] = fac.first * i / fac.second + A[i - 1];↵
    ll res = 0;↵
    for (int i = 1; i <= n; i ++ ) res += mu[i] * A[n / i];↵
    return res;↵
}↵

PII rank_to_fraction(ll k) {↵
    ll l = 0, r = n;↵
    while (l < r) {↵
        ll mid = l + r + 1 >> 1;↵
        if (fraction_to_rank({mid, n}) <= k) l = mid;↵
        else r = mid - 1;↵
    }↵
    k -= fraction_to_rank({r, n});↵
    PII a = {r / __gcd(r, n), n / __gcd(r, n)}, b = nxt_fraction(a);↵
    if (!k) return a;↵
    while (k -- ) a = nxt_fraction(a, b), swap(a, b);↵
    return a;↵
}↵

void solve() {↵
    cin >> n;↵
    PII now = {1, n};↵
    while (now.first != now.second) {↵
        ll rk = fraction_to_rank(now);↵
        PII fac = rank_to_fraction(rk);↵
        cout << rk << " : " << fac.first << " " << fac.second << " | " << now.first << " " << now.second << "\n";↵
        now = nxt_fraction(now);↵
    }↵
}↵

int main() {↵
    ios::sync_with_stdio(false);↵
    cin.tie(0), cout.tie(0);↵
    init_mu();↵
    int T = 1;↵
    // cin >> T;↵
    while (T -- ) solve();↵
    return 0;↵
}↵
```↵

## Expansion↵

Knowing one term, the time complexity of solving for the next term is $O(n + \log{n})$. To find the closest fraction $\frac{c}{d}$ that satisfies $bc - ad = 1$, we can use the Extended Euclidean Algorithm. Since the difference between two adjacent terms is $\frac{1}{bd}$, we only need to maximize $d$.↵

On the other hand, it is easy to see that we rarely encounter situations where $x$ is an irrational number in practical problems. Therefore, we can naturally assume $x = \frac{p}{q}$, giving us↵

$$\sum\limits_{d = 1}^{n}\mu(d)\sum\limits_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}\lfloor x \cdot i \rfloor = \sum\limits_{d = 1}^{n}\mu(d)\sum\limits_{i = 1}^{\left\lfloor\frac{n}{d}\right\rfloor}\left\lfloor \frac{pi}{q} \right\rfloor$$↵

It is easy to see that the latter is the standard form for our Euclidean-like algorithm. By using number theory block division (square root decomposition), we can achieve $O(\sqrt{n}\log^2{n})$ per query.↵

Furthermore, you can use the Du Sieve to sum the preceding Möbius function, reducing the precomputation time complexity to $O(n^{\frac{2}{3}})$.↵

If you still feel this method is not optimal, you can utilize Dirichlet prefix sums with block processing, achieving an astonishing overall time complexity of $O(n^{\frac{2}{3}} + \sqrt{n}\log^{\frac{3}{2}}{n})$.↵

```cpp↵
#include<bits/stdc++.h>↵
using namespace std;↵
#define ll long long↵
#define PII pair<ll, ll>↵
const int N = 1e5;↵
ll n, k;↵
ll primes[N], st[N], mu[N], cnt;↵
unordered_map<ll, ll> summu;↵

// precalculate Mu↵
void init_mu() {↵
    mu[1] = 1;↵
    for (int i = 2; i < N; i ++ ) {↵
        if (!st[i]) primes[cnt ++ ] = i, mu[i] = -1;↵
        for (int j = 0; i * primes[j] < N; j ++ ) {↵
            st[i * primes[j]] = 1;↵
            if (i % primes[j] == 0) break;↵
            mu[i * primes[j]] = -mu[i];↵
        }↵
    }↵
    for (int i = 2; i < N; i ++ ) mu[i] += mu[i - 1];↵
}↵

ll get_mu(ll n) {↵
    if (n < N) return mu[n];↵
    if (summu.count(n)) return summu[n];↵
    ll res = 1;↵
    for (ll l = 2, r; l <= n; l = r + 1) {↵
        r = n / (n / l);↵
        res -= (r - l + 1) * get_mu(n / l);↵
    }↵
    return summu[n] = res;↵
}↵

ll f(ll a, ll b, ll c, ll n) {↵
if (!a) return b / c * (n + 1);↵
if (a < c && b < c) {↵
ll m = (a * n + b) / c;↵
if (!m) return 0;↵
return n * m - f(c, c - b - 1, a, m - 1);↵
}↵
return f(a % c, b % c, c, n) + (n + 1) * n / 2 * (a / c) + (n + 1) * (b / c);↵
}↵

// O(logn) calculate next one by one↵
PII nxt_fraction(ll n, PII fac) {↵
    ll a = fac.first, b = fac.second, c, d;↵
    exgcd(b, a, c, d);↵
    d = -d;↵
    if (d <= 0) {↵
        ll k = (-d + b - 1) / b;↵
        c += k * a;↵
        d += k * b;↵
    }↵
    ll k = (n - d) / b;↵
    return {c + k * a, d + k * b};↵
}↵

// O(1) calculate next one by two nearly↵
PII nxt_fraction(ll n, PII fac1, PII fac2) {↵
    auto [a, b] = fac1;↵
    auto [c, d] = fac2;↵
    return {(n + b) / d * c - a, (n + b) / d * d - b};↵
}↵

// O(sqrt(n)logn) calculate fraction's rank↵
ll fraction_to_rank(ll n, PII fac) {↵
    ll res = 0;↵
    for (ll l = 1, r; l <= n; l = r + 1) {↵
        r = n / (n / l);↵
        res += (get_mu(r) - get_mu(l - 1)) * f(fac.first, 0, fac.second, n / l);↵
    }↵
    return res;↵
}↵

// O(sqrt(n)log(n)^2) calculate the fraction of k-th rank↵
PII rank_to_fraction(ll n, ll k) {↵
    ll l = 0, r = n;↵
    while (l < r) {↵
        ll mid = l + r + 1 >> 1;↵
        if (fraction_to_rank(n, {mid, n}) <= k) l = mid;↵
        else r = mid - 1;↵
    }↵
    k -= fraction_to_rank(n, {r, n});↵
    PII a = {r / __gcd(r, n), n / __gcd(r, n)}, b = nxt_fraction(n, a);↵
    if (!k) return a;↵
    while (k -- ) a = nxt_fraction(n, a, b), swap(a, b);↵
    return a;↵
}↵

void solve() {↵
    cin >> n;↵
    PII now = {1, n};↵
    while (now.first != now.second) {↵
        ll rk = fraction_to_rank(n, now);↵
        PII fac = rank_to_fraction(n, rk);↵
        cout << rk << " : " << fac.first << " " << fac.second << " | " << now.first << " " << now.second << "\n";↵
        now = nxt_fraction(n, now);↵
    }↵
}↵

int main() {↵
    ios::sync_with_stdio(false);↵
    cin.tie(0), cout.tie(0);↵
    init_mu();↵
    int T = 1;↵
    // cin >> T;↵
    while (T -- ) solve();↵
    return 0;↵
}↵
```

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en2 English YipChip 2026-05-27 17:14:22 58
en1 English YipChip 2026-05-27 17:13:11 13390 Initial revision (published)