二分经典题,
注意INF不能开太小(WA),也不能开太大(会T)。。
/* f(i)=i*i+(100000+j)*i-(100000-j)*j f(i)是对i的递增函数,外层二分mid答案,内层枚举j二分i寻找有多少<=mid 复杂度O(lognlogn * n) */ #include<iostream> #include<cstring> #include<cstdio> #define maxn 50050 #define ll long long #define INF 1000000000000 using namespace std; long long n,m,t; inline long long f(ll i,ll j){return i*i+100000*i+j*j-100000*j+i*j;} inline long long check(ll x){//枚举每个j,二分找使f(i)<=x的个数,并累加 ll res=0; for(ll j=1;j<=n;j++){ ll l=1,r=n,mid,ans=0; while(l<=r){ mid=l+(r-l)/2; if(f(mid,j)<=x) //值比x小 ans=mid,l=mid+1; else r=mid-1; //值比x大 } res+=ans; } return res; } int main(){ scanf("%I64d",&t); while(t--){ scanf("%I64d%I64d",&n,&m); ll l=-(ll)INF,r=INF,mid,ans=0; while(l<=r){ mid=l+(r-l)/2; if(check(mid)<m)//mid取值小 l=mid+1; else ans=mid,r=mid-1; } printf("%I64d ",ans); } }