快轉到主要內容

CF Edu Binary Search -- Step 5 pB Multiplication Table

目錄

題目
#

給你 \(n\) 和 \(k\),請求出 \(n\times n\) 乘法表中第 \(k\) 小的數字。

解題思路
#

直接建表排序太慢了,時間複雜度高達 \(O(n^2 \times log(n))\),我們需要一個更快的方法。題目是詢問第 \(k\) 小的數字,答案範圍又很大,有機會可以用「第 \(k\) 大二分搜」解決(雖然這邊是第 \(k\) 小)。

對於每一個答案,使用雙指針,一個設為 \(1\),另外一個設為 \(n\)。當第一個指針增加的時候,第二個指針要一直減一,直到兩個指針乘積 \(\leq\) 答案。第二個指針所停留的數字就是在其中一個數字為第一個指針的時候,能讓兩指針相乘不超過答案的數字個數。將他們相加就能得到乘法表中有多少個數小於等於答案。

常見錯誤
#

  • 記得開 long long( \(k\) 和答案最大都高達 \(10^{10}\) )

完整程式碼
#

#include <bits/stdc++.h>

using namespace std;

int main() {
    long long n, k;
    cin >> n >> k;
    long long l = 0, r = 1e10;
    while (l < r) {
        long long m = (l + r) / 2;
        long long cnt = 0;
        long long p1 = n;
        for (int p2 = 1; p2 <= n; p2++) {
            while (p1 * p2 > m){
                p1--;
            }
            cnt += p1;
        }
        if (cnt < k) {
            l = m + 1;
        }
        else{
            r = m;
        }
    }
    cout << l << "\n";
}
Piau 的筆記本
作者
Piau 的筆記本
希望我寫下來的東西能夠長久的記在我的腦中