Matrix
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 4468 | Accepted: 1110 |
Description
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
最开始无法确定第k小的是谁,则先猜想一个答案,然后带回矩阵中看是否满足条件 这时二分优势便体现出来了,先确定一个mid值,然后枚举每列(因为可以看出每列从上到下是递增的) 找到比mid小的有多少个,如果大于k值,则说明mid的值偏大,减小mid的值,反之增大mid的值 这里我采用了男神的方法采用用ans更新中间值,则避免了取整的问题。。
#include<cstdio> #include<cmath> typedef long long ll;// 第一次使用,原来如此简单 long long m; long long cal(long long i,long long j) { return i*i+100000*i+j*j -100000*j +i*j; } int main() { int T; ll t,ans,sum,n; ll i,j,mid; ll left,right,le,ri,midmid,calmid,tmp; scanf("%d",&T); while(T--) { scanf("%lld%lld",&n,&m); right=7500000000; left=-right; while(left<=right) { sum=0; mid=(left+right)/2;//二分答案 for(j=1;j<=n;j++) { le=1; ri=n; tmp=0; while(le<=ri) { //找到比mid值小的个数 midmid=(le+ri)/2; calmid=cal(midmid,j); if(calmid<=mid) { tmp=midmid; le=midmid+1;//因为是找到比mid小的,所以calmid<mid时则增大mid的值 } else ri=midmid-1; } sum=sum+tmp; } if(sum<m) left=mid+1;//比第m还小,则增大值 else { ans=mid; right=mid-1; } } printf("%lld\n",ans); } return 0; }