/*
给定n,有n*n个数,有aij=i * i + m * i + j * j - m * j + i * j
n <= 50000
m <= 100000
求所有aij中第m大的数
还是二分答案,先根据生成的式子,求出最大的和最小的数字,然后二分答案,验证
我们发现,对于同列的数字,按照行数的增加,数字大小是递增的
根据这个性质,就很容易验证是否存在>=n*n-m+1个数字>=val了
看了题一下子就有想法了,结果却wa了一天...原因在于自作聪明地进行数学推论然后非要从同行中进行二分...最后才发现不满足递减性质...不过最后ac的时候还是很爽快的
*/
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define range(i,a,b) for (long long i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll m = 1e5;
ll n;
ll M;
inline ll Int(ll i,ll j)
{
return i * i + m * i + j * j - m * j + i * j;
}
//找到最小的i,满足>=val
ll findK(ll j,ll val)
{
ll l(1),r(n);
while(l+1<r)
{
int mid = (l+r)>>1;
if (Int(mid,j) >= val)
r = mid;
else
l = mid;
}
//返回>=val的数字的个数
if (Int(l,j) >= val)
return n-l+1;
if (Int(r,j) >= val)
return n-r+1;
return 0;
}
bool test(ll val)
{
ll ans(0);
//返回每一行的>=val的数量
range(c,1,n)
{
ans += findK(c,val);
}
return ans >= (ll)n*n - M+1;
//必须要有>=n*n-M+1的数量>=ans,ans才有可能是答案
}
int main()
{
int t;
cin>>t;
range(c,1,t)
{
cin>>n>>M;
ll l(-n*m),r(n*n*3 + n*m);
while(l+1<r)
{
ll mid = (l+r)/2;
if (mid == 5101786214)
{
cout<<"";
}
if (test(mid))
{
l = mid;
}
else
{
r = mid;
}
}
if (test(r))
{
cout<<r<<endl;
}
if (test(l))
{
cout<<l<<endl;
}
}
return 0;
}