题意:给你一个公式,i行,j列,表示这个矩阵里i行j列的数是i^2 + 100000 × i + j^2 - 100000 × j + i × j.
求这个矩阵第m大的数。
思路:数学差的看不出这个公式的规律,可以先输出几行发现,每列从上往下递增,从左往右递增。
所以这个二分的判断函数里面也是二分查找比x小的个数,在进行判断。
详细见代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n,m;
ll cal(ll i,ll j){
return i*i+100000*i+j*j-100000*j+i*j;
}
bool check(ll x)
{
ll num=0;
for(int j=n;j>=1;j--){
if(cal(1,j)>x) break;//剪枝,由于从左往右的列,依次递增,同时每行依次递增,所以如果第一个就大于x,以后就不用找了,都是大于x.
int l=1,r=n;
while(l<=r){
int mid=(l+r)/2;
if(cal(mid,j)<x) l=mid+1;
else r=mid-1;
}
num+=(l-1);
}
return num>=m;
}
int main()
{
int T;scanf("%d",&T);
while(T--){
scanf("%lld %lld",&n,&m);
ll l=-100000*n,r=n*n*3+100000*n;
while(l<=r){
ll mid=l+(r-l)/2;
if(!check(mid)) l=mid+1;
else r=mid-1;
}
printf("%lld\n",l-1);
}
}