题目
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
题解
先开始上去肯定还是找规律的,但是在推了一下后面发现,其实并不包含某种单调性。考虑一下而二分答案,二分mid为答案值,然后因为在i或者j固定的时候答案是单调变化的,所以我们在一个列里面去二分一下num,把num相加,看下是否大于k值,继续二分找到答案即可。
代码实现
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,k;
ll f (ll x,ll y) {
return x*x+100000*x+y*y-100000*y+x*y;
}
bool check (ll x) {
ll num=0;
for (ll i=1;i<=n;i++) {
ll l=0,r=n,mid;
while (l<r) {
mid=(l+r+1)/2;
if (f (mid,i)<=x) l=mid;
else r=mid-1;
}
num+=l;
}
return num>=k;
}
int main () {
int t;
scanf ("%d",&t);
while (t--) {
scanf ("%lld%lld",&n,&k);
ll l=-1e12,r=1e12;
ll ans;
while (l<r) {
ll mid=(l+r)>>1;
if (check (mid)) r=mid;
else l=mid+1;
}
printf ("%lld
",l);
}
return 0;
}