CodeChef:Desik And Divisors(数学 & 二分 & 思维)

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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值