poj3685Matrix

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值