Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix.
Input
The first line of input is the number of test case.
For each test case there is only one line contains two integers, N(1 ≤ N ≤ 50,000) and M(1 ≤ M ≤ N × N). There is a blank line before each test case.
Output
For each test case output the answer on a single line.
Sample Input
12
1 1
2 1
2 2
2 3
2 4
3 1
3 2
3 8
3 9
5 1
5 25
5 10
Sample Output
3
-99993
3
12
100007
-199987
-99993
100019
200013
-399969
400031
-99939
思路:
1.根据这个 aij=i*i + 100000 × i + j*j - 100000 × j + i × j 可以得出当j不变时,aij随i增大而增大,即:在当列确定,行从上往下是单调递增的。
2.要-求第m小的aij,可以对aij范围的值二分,然后判断当前的mid值是否满足ans>=m (ans表示比mid值小的aij的数量)
3.怎么判断ans>=m,根据1中每列是单调递增的,可以对每列二分,求出每列比mid值小的aij的数量,然后求和--求出的就是这个矩阵中比mid小的aij的数量
代码:
import java.util.Scanner;
public class main13 {
static long n,m;
static final long INF=(long) 1e12;
public static long cal(long i,long j){
return i*i+100000*i+j*j-100000*j+i*j;
}
public static boolean check(long x){
long ans=0;
for(int i=1;i<=n;i++){
long l=1,r=n,mid=0,c=0;
while(l<=r){
mid=(l+r)/2;
if(cal(mid,i)<=x){//这样写求出来的是比mid小的数量
l=mid+1;
c=mid;
}
else
r=mid-1;
}
ans+=c;
}
if(ans>=m) return true;
else return false;
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int t=scan.nextInt();
while(t!=0){
n=scan.nextLong();
m=scan.nextLong();
long l=-INF,r=INF,mid=0;
long c=0;
while(l<=r){
mid=(l+r)/2;
if(check(mid)){//满足and>=m,就可以继续缩小范围继续判断,直到下一个mid不满足,那么上一个mid就满足条件
r=mid-1;
c=mid;
}
else
l=mid+1;
}
System.out.println(c);
t--;
}
}
}