Matrix POJ - 3685 点击打开链接
给出一个N*N的矩阵,第i行第j列的值为i*i + 100000*i + j*j - 100000*j + i*j,求矩阵中第 M 小的数。
思路: 二分+二分。
分析:由i*i + 100000*i + j*j - 100000*j + i*j这个公式,可知i是单调递增的。所以,我们可以第一次二分答案mid,第二次根据i的单调性依次二分每一列,得到比mid小的数的个数,如果总个数小于M的话,则说明mid小了。
from 点击打开链接
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
ll n,m;
ll cal(ll i,ll j)
{
return i*i+j*j+100000*i-100000*j+i*j;
}
bool solve(ll mid)
{
ll cnt=0;
for(ll j=1;j<=n;j++)
{
ll R=n+1;
ll L=0;
while(R-L>1)
{
ll midd=(R+L)>>1;
if(cal(midd,j)<mid)
L=midd;
else
R=midd;
}
cnt+=L;
}
return cnt<m;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
ll L=-100000*n;
ll R=n*n+100000*n+n*n+n*n;
while(R-L>1)
{
ll mid=(L+R)/2;
if(solve(mid))
L=mid;
else R=mid;
}
printf("%lld\n",L);
}
return 0;
}