Given two integers L and K. You are to find the minimum integer R such that Sum of the number of divisors of all numbers from L to R is greater than K.
Input
- First Line specifies an integer T, the number of test cases.
- Every Test case consists of two integers L and K as described in problem statement.
Output
- For every test case print, the value of R in a new line and print - 1 if R - L > 10 ^ 9.
Constraints
Should contain all the constraints on the input data that you may have. Format it like:
- 1 ≤ T ≤ 20
- 1 ≤ L ≤ 10 ^ 9
- 1 ≤ K ≤ 10 ^ 18
Example
Input: 2 5 20 5 28 Output: 11 13题意:给出L和K,要求找出最小的R,使得[L,R]区间的数的因子数目之和大于K,若R-L>1e9就输出-1。
思路:二分R,验证1~R因子数目和减去1~L-1的因子数目和是否>K。计算1~X的因子数目和参考代码,其实很好理解枚举整除<=sqrt X的因子数,乘二就是总的因子数。但是有些两个因子都在sqrt X里面刚好重复计算了两次,再减去sqrt X * sqrt X就行。
CODE_1
# include <iostream>
# include <cmath>
# include <cstdio>
using namespace std;
typedef long long LL;
LL cal(LL x)
{
LL res = 0, sq = sqrt(x);
for(int i=1; i<=sq; ++i) res += x/i;
return res*2-sq*sq;
}
int main()
{
LL l, k;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&l,&k);
if(cal(l+1e9)-cal(l-1) <= k)
{
puts("-1");
continue;
}
LL r = 1e9+l, left = cal(l-1);
while(l < r)
{
LL mid = l+r>>1;
if(cal(mid)-left>k) r = mid;
else l = mid+1;
}
printf("%lld\n",r);
}
return 0;
}
CODE_2
暴力计算n/1+n/2+n/3+...+n/n
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL l, k, a;
LL check(LL x)
{
LL sum = 0;
for(int i=1,j; i<=x; i=j+1)
{
j=x/(x/i);
sum += 1LL*(j-i+1)*(x/i);
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&l,&k);
a=check(l-1);
LL L=l+1, R=l+1e9;
while(L<=R)
{
LL mid = L+R>>1;
if(check(mid)-a>k) R=mid-1;
else L=mid+1;
}
printf("%d\n",L-l>1e9?-1:L);
}
return 0;
}