题目:http://poj.org/problem?id=3685
潜意识里,我就打表找规律了,果不其然就WA了...
正确姿势是二分,因为在j确定的情况下:i2 + 100000 × i + j2 - 100000 × j + i × j 会随着i的增大而递增,也就是说我们可以很快地知道某一列有多少个数<val;
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<t;i++)
typedef long long ll;
int t,n;
ll m;
inline ll Cal(int i,int j){
return i*1LL*i+100000*1LL*i+j*1LL*j-100000*1LL*j+i*1LL*j;
}
inline ll Sum(ll val){
ll num=0;
rep(i,1,n+1){
int s=1,t=n;
while(s<=t){
int mid=(s+t)>>1;
ll v=Cal(mid,i);
if(v<=val) s=mid+1;
else t=mid-1;
}
num+=s-1;
}
return num;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%lld",&n,&m);
ll l=-1000000000000*1LL,r=1000000000000*1LL;
while(l<=r){
//printf("%lld %lld ",l,r);
ll mid=l+(r-l)/2;
ll v=Sum(mid);
if(v<m) l=mid+1;
else r=mid-1;
// printf("%lld %lld %lld %lld \n",l,r,mid,v);
}
printf("%lld\n",l);
}
return 0;
}