Topics

In this problem, we are given an multiplication table where the entry at position is . Find the -th number when all numbers are sorted in non-decreasing order.

Idea

The smallest value in the table is . The largest value is . Thus, our search space for the -th number lies within the range .

We can use binary search, but we need a function that, for a given candidate value , tells us how many numbers in the multiplication table are . Let’s consider row . The numbers in row are . The count of numbers in row that are is given by:

Summing this count over all rows from to gives us the total count of numbers in the table that are :

Since is monotonic, and we need to find the smallest for which , we can use the binary search boolean array framework. Evaluating check(x) = (count(x) >= k) for every value of in our search space would generate a boolean array: 0,0,...,0,1,1,...,1. Our goal is to find the transition point, i.e. the first 1.

Note that this works correctly for duplicates as seen for the example:

Example

We have n=2, m=3, table=[1, 2, 2, 3, 4, 6] and we want the -nd element which’s 2. Observe that when , we have and for , . Thus, check(1) is false while check(2) is true and will be returned as answer since it’s the transition point.

Warning

Even though our search space includes elements that aren’t in the table (e.g. 5 in this case), this transition point must occur at one of the actual table values , ensuring the correctness of the solution.

Time Complexity:
Space Complexity:

Code

#include <bits/stdc++.h>
using namespace std;
 
#define ll long long
 
bool check(ll mid, ll n, ll m, ll k) {
    ll cnt = 0;
    for (ll i = 1; i <= n; i++) {
        // Count how many numbers in row i are <= mid
        // which is min(mid/i, m)
        cnt += min(mid / i, m);
    }
    return (cnt >= k);
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    ll n, m, k;
    cin >> n >> m >> k;
 
    ll lo = 1;
    ll hi = n * m;
    ll ans = hi;
 
    // Binary search for the k-th smallest
    while (lo <= hi) {
        ll mid = (lo + hi) / 2;
        if (check(mid, n, m, k)) {
            ans = mid;
            hi = mid - 1;
        } else {
            lo = mid + 1;
        }
    }
 
    cout << ans << "\n";
    return 0;
}