1. 程式人生 > >POJ 3685 二分套二分

POJ 3685 二分套二分

lan ber com 題解 ans a + b number algo 不知道

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 ≤ MN × 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


剛看到題的時候依舊一臉懵逼,不知道從哪開始下手,還是向大佬的題解妥協了

式子是關於i單調遞增的(求偏導……都會得……嗯……)然後,找突破口

先二分答案x,然後二分的去找每行<x的個數,根據小於x的個數來調整x的大小。。。——二分套二分……

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<algorithm>
typedef long long ll;
using namespace std;
ll n, m,t;
bool judge(ll a, ll b,ll c) { return (a*a + 100000*a + b*b - 100000*b + a*b)<c; } bool C(ll x) { ll crt = 0; for (int i = 1; i <= n; i++) //i從1開始 { ll le = 0, r = n + 1; while (le<r-1) //找沒行多少個小於mid的 { ll mi = (r + le) /2 ; if (judge(mi, i, x)) le = mi; else r = mi; } crt += le; } return crt < m; } int main() { scanf("%lld", &t); while (t--) { scanf("%lld%lld",&n, &m); ll l = -100000*n, h = 3*n*n+100000*n; //不懂為什麽換成inf就WA while(h-l>1) { ll mid = (h + l) / 2; if (C(mid)) l = mid; else h = mid; } printf("%lld\n", l); } return 0; }

POJ 3685 二分套二分