题目描述
难度分:999
输入n,m(1≤n,m≤1012)。
选两个不超过n的正整数a和b,使得a×b至少为m。
输出a×b的最小值。如果不存在这样的a和b,输出−1。
输入样例1
5 7
输出样例1
8
输入样例2
2 5
输出样例2
-1
输入样例3
100000 10000000000
输出样例3
10000000000
算法
数学
在[1,n]的范围内遍历a的可能取值,对于某个a,要想a×b≥m,则b至少要为[b+a−1a](ba的向上取整),其中[.]为对.的向下取整操作。而此时我们可以发现,如果老老实实遍历完a,那n≤1012一定会超时。因此还需要用m进一步限制范围,由于a×b最小限度超过m就可以了,所以a2不会超过m太多,只需要遍历到O(√m)这个量级。
按照以上的准则得到a和b的候选,在b≤n时维护a×b的最小值即可。
复杂度分析
时间复杂度
主要受到外层循环的限制,时间复杂度为O(min(n,√m))。
空间复杂度
只使用了有限几个变量,额外空间复杂度为O(1)。
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <limits.h>
using namespace std;
typedef long long LL;
LL n, m;
int main() {
scanf("%lld%lld", &n, &m);
LL x = LLONG_MAX;
for(LL a = 1; a <= n && a*a <= m*2; a++) {
LL b = (m + a - 1)/a; // 此时要保证a*b>=m,b至少为这个数
if(b <= n) {
x = min(x, a*b);
}
}
if(x == LLONG_MAX) x = -1;
printf("%lld\n", x);
return 0;
}