网易19实习编程题:数对

时间限制:1秒

空间限制:32768K

牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。 但是牛牛记得老师告诉过他x和y均不大于n,
并且x除以y的余数大于等于k。

牛牛希望你能帮他计算一共有多少个可能的数对。

输入描述:

输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。

输出描述:

对于每个测试用例, 输出一个正整数表示可能的数对数量。

输入例子1:

5 2

输出例子1:

7

例子说明1:

满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)

分析:
朴素的做法是枚举n^2个点然后跟k作比较。这显然对n<=100000的规模来说是不允许通过的。
注意到当除数是y时,当x=1~n时,余数是1,2,3,…,y-1,0循环出现,循环节长度显然是y。
那么我们可以枚举y=k~n(当y小于k时所有余数均小于k,因此不需要考虑)
然后对于x=1~n,总共出现了[n/y]个循环节,然后数出每个循环节里面不小于k的余数。最后再数出不满一个循环节的不小于k的余数,就是答案了。注意当k=0的时候由于余数0出现在循环的末尾,因此要特别判断。
复杂度为O(n) 。

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        long n=sc.nextInt();
        long k=sc.nextInt();
        long res=0;//可能结果会大于int范围(43亿),必须要用long
        if(k==0){
            System.out.println(n*n);
        }else{
            for(long y=k;y<=n;y++){//小于k时余数0
                res+=(n/y)*(y-k)+Math.max(0,n%y-k+1);//循环节部分+不构成循环节的部分
            }
            System.out.println(res);
        }
    }
}

你可能感兴趣的:(java,daily_code)