首页 > 代码库 > POJ 3685 二分套二分

POJ 3685 二分套二分

Matrix

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
代码:
 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string.h>
 5 #include<math.h>
 6 #include<stdlib.h>
 7 #include<ctype.h>
 8 #include<stack>
 9 #include<queue>
10 #include<map>
11 #include<set>
12 #include<vector>
13 #define ll long long
14 #define  db double
15 using namespace std;
16 const int N=1e6+5;
17 const int mod=1e9+7;
18 ll f(ll x,ll y)
19 {
20     return (x*x+100000*x+y*y-100000*y+x*y);
21 }
22 ll n,m;
23 ll cal(ll x){
24     ll cnt=0,ans=0;
25     for(ll i=1;i<=n;i++){
26         ll sl=1,sr=n;
27         while (sl<=sr){
28             ll mid=(sr+sl)/2;
29             if(f(mid,i)<=x){
30                 ans=mid;
31                 sl=mid+1;
32             }
33             else sr=mid-1;
34         }
35         cnt+=ans;
36     }
37     return  cnt;
38 }
39 int main(){
40     int t;
41     scanf("%d",&t);
42     while (t--)
43     {
44         scanf("%lld%lld",&n,&m);
45         ll l=-100000*n,r=n*n+100000*n+n*n+n*n;
46         ll ans=0;
47         while (l<=r){
48             ll mid=(l+r)/2;
49             if(cal(mid)>=m) {ans=mid;r=mid-1;}
50             else {l=mid+1;}
51         }
52         printf("%lld\n",ans);
53     }
54     return 0;
55 }

 

POJ 3685 二分套二分