逆向思维,二分查找答案。
对于一个n*m乘法表,要查数字n前有多少小于等于n的,可用
ll solve(ll t){
ll res=0;for(int i=1;i<=n;i++){
ll tmp=t/i;
if(tmp>m)
tmp=m;
res+=tmp;
}
return res;
}
二分时若solve(n)<k则肯定不是想要的n,使l=mid+1,但若solve(n)==k时可能是想要的n,也可能不是(n不一定属于乘法表),所以应令r=mid
代码:
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
long long n,m,k;
ll solve(ll t){
ll res=0;
for(int i=1;i<=n;i++){
ll tmp=t/i;
if(tmp>m)
tmp=m;
res+=tmp;
}
return res;
}
int main(){
while(~scanf("%I64d%I64d%I64d",&n,&m,&k)){
ll l=1;
ll r=n*m+1;
ll mid;
while(l<r){
mid=(l+r)/2;
if(solve(mid)<k)
l=mid+1;
else
r=mid;
}
mid=(l+r)/2;
printf("%I64d\n",mid);
}
return 0;
}