题目大意:给出一个矩阵,矩阵下标是从1开始计数,矩阵中的值由下标相乘得到(i*j)。任意给出一个数k,能快速找到矩阵经过排序后对应的第k个数。
解题思路:通过二分查找来确定数字k所在的位置。在每次二分查找中判断中间值 (mid) 和每一行最后一列数值的大小 (i*m),累加(m)或(mid/i),i表示行数。用累加和来判断与k的大小。
package 百度;
import java.util.Scanner;
/**
* 题目描述 度度熊和爷爷在玩一个乘法表游戏。乘法表的第i行第j列位置的元素为i*j,并且乘法表下标编号从1开始,比如2 × 3乘法表为
* 1 2 3
* 2 4 6
* 爷爷十分聪明,对于n*m的乘法表,只要度度熊给出一个数k,爷爷就能立刻告诉度度熊乘法表中元素按照不减顺序排列之后,第k个元素是多少。你能重复这个游戏吗?
*
* 输入: 输入数据是三个整数:n, m, k (1≤n, m≤5*105, 1≤k≤nm)。
* 样例输入 2 3 4
* 输出:n*m乘法表按照不减顺序排列的第k个数。 样例输出 3
*
* 解题思路:
*
* @author 崔洪振367
* @version 创建时间:2017年5月5日 下午5:05:04
*/
public class Q2016实习_乘法表 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
long n = sc.nextLong();// i,行
long m = sc.nextLong();// j,列
long k = sc.nextLong();
long left = 1;
long right = n * m;//样例:2*3
long mid = right / 2;//mid为6/2=3,中间位置的数字应该是3
while (left <= right) {
mid = (left + right) / 2;
long sum = 0;
for (int i = 1; i <= n; i++) {
long temp = (mid >= i * m) ? m : mid / i;//判断mid和每一行的最后一个数的大小
sum += temp;
}
if (sum < k) {
left = mid + 1;
} else {
right = mid - 1;
}
}
System.out.println(left);
}
sc.close();
}
}