---
# System prepended metadata

title: 786. K-th Smallest Prime Fraction
tags: [C++, LeetCode]

---

# LeetCode 786. K-th Smallest Prime Fraction

https://leetcode.com/problems/k-th-smallest-prime-fraction/description/

## 題目大意

給定已排序的整數陣列 `arr`，裡面包含了 `1` 和質數，而且 `arr` 中所有整數全相異
題目還給了一個整數 `k`

對於 `arr` 中的每一對 `i` 和 `j`，考慮分數 `arr[i] / arr[j]` (`i` $\lt$ `j`)

回傳第 `k` 小的分數
其中 `answer[0] == arr[i]` 、 `answer[1] == arr[j]`

## 思考

因為題目排序過，所以如果問最小的，那肯定是頭除以尾
不過這題問的是第 `k` 個……

等等，想到了嗎？問第 `k` 個，不過題目有幫我們**排序**過了……

是的，這題我們可以用 binary search ，排序過算是一個提示

```cpp!
class Solution
{
public:
    vector<int> kthSmallestPrimeFraction(vector<int> &arr, int k)
    {
        double l = 0, r = 1;
        const int n = arr.size();

        while (l < r)
        {
            const double mid = (l + r) / 2.0;
            int p = 0, q = 1, cnt = 0;

            for (int i = 0, j = 1; i < n; ++i)
            {
                while (j < n && arr[i] > mid * arr[j])
                    ++j;

                if (j == n)
                    break;

                cnt += n - j;
                if (p * arr[j] < q * arr[i])
                {
                    p = arr[i];
                    q = arr[j];
                }
            }

            if (cnt == k)
                return {p, q};

            if (cnt < k)
                l = mid;
            else
                r = mid;
        }

        throw;
    }
};
```

對於每個 `i` ，我們先找到第一個 `j` 滿足 $\frac{\mathrm{arr}[i]}{\mathrm{arr}[j]} \le mid$

那麼我們就知道不大於 `mid` 的分數總共有 `n - j` 個
這是本題的一大關鍵想法

然後我們每次都要更新 $\frac{p}{q}$ 成最大

最後，如果 `cnt == k` 即為題意
