二分。
刚开始做这题的时候,只是脑补出了这种做法,直觉告诉我它应该是对的,但并不会证明。
抱着试试看的心态打了一发,居然A了……
题解:http://vfleaking.blog.uoj.ac/blog/694
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
long long n, m, r, left, right;
scanf("%lld%lld%lld",&n,&m,&r);
left=1, right=n*m;
if(!r)
{
return !printf("%lld\n",min(n*m,2ll));
}
else if(n==1||m==1)
{
while(left<right)
{
long long mid=(left+right+1)>>1;
if((mid-1)*(mid-2)/2<=r)left=mid;
else right=mid-1;
}
}
else
{
while(left<right)
{
long long mid=(left+right+1)>>1, pre, s, h;
s=sqrt(mid);
h=mid-s*s;
if((s+1*(h!=0))<=n && (s+1*(h!=0))<=m)
{
pre=2*(s-1)*(s-1)+2*s-2;
if(h)pre+=(h-1)*2+1;
if(h>s)pre+=(h-s-1)*2+1;
}
else
{
s=min(n,m);
h=mid/s;
pre=2*(s-1)*(h-1)+s+h-2;
h=mid%s;
if(h)pre+=(h-1)*2+1;
}
if(1.0*mid*(mid-1)/2<=r+pre)left=mid;
else right=mid-1;
}
}
printf("%lld\n",left);
return 0;
}