\Big\lfloor\dfrac{x}{n}\Big\rfloor\cdot n + \sum_{i=\Big\lfloor\dfrac{x}{n}\Big\rfloor+1}^{m} \Big\lfloor\dfrac{x}{i}\Big\rfloor
由于 x 越大上式越大,x 越小上式越小,因此我们可以二分 x 找到答案,二分的初始边界为乘法表的元素范围,即 [1,mn]。
[sol1-Python3]
1 2 3
classSolution: deffindKthNumber(self, m: int, n: int, k: int) -> int: return bisect_left(range(m * n), k, key=lambda x: x // n * n + sum(x // i for i inrange(x // n + 1, m + 1)))
[sol1-C++]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: intfindKthNumber(int m, int n, int k){ int left = 1, right = m * n; while (left < right) { int x = left + (right - left) / 2; int count = x / n * n; for (int i = x / n + 1; i <= m; ++i) { count += x / i; } if (count >= k) { right = x; } else { left = x + 1; } } return left; } };
[sol1-Java]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { publicintfindKthNumber(int m, int n, int k) { intleft=1, right = m * n; while (left < right) { intx= left + (right - left) / 2; intcount= x / n * n; for (inti= x / n + 1; i <= m; ++i) { count += x / i; } if (count >= k) { right = x; } else { left = x + 1; } } return left; } }
[sol1-C#]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
publicclassSolution { publicintFindKthNumber(int m, int n, int k) { int left = 1, right = m * n; while (left < right) { int x = left + (right - left) / 2; int count = x / n * n; for (int i = x / n + 1; i <= m; ++i) { count += x / i; } if (count >= k) { right = x; } else { left = x + 1; } } return left; } }
[sol1-Golang]
1 2 3 4 5 6 7 8 9
funcfindKthNumber(m, n, k int)int { return sort.Search(m*n, func(x int)bool { count := x / n * n for i := x / n + 1; i <= m; i++ { count += x / i } return count >= k }) }
[sol1-C]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
intfindKthNumber(int m, int n, int k){ int left = 1, right = m * n; while (left < right) { int x = left + (right - left) / 2; int count = x / n * n; for (int i = x / n + 1; i <= m; ++i) { count += x / i; } if (count >= k) { right = x; } else { left = x + 1; } } return left; }
[sol1-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var findKthNumber = function(m, n, k) { let left = 1, right = m * n; while (left < right) { const x = left + Math.floor((right - left) / 2); let count = Math.floor(x / n) * n; for (let i = Math.floor(x / n) + 1; i <= m; ++i) { count += Math.floor(x / i); } if (count >= k) { right = x; } else { left = x + 1; } } return left; };