牛客网系列--网易2019实习生招聘编程题--数对

题目:

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

输入描述:
输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。
输出描述:
对于每个测试用例, 输出一个正整数表示可能的数对数量。
示例1
输入
5 2
输出
7
说明
满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)

解题思路:

当我们确定了除数y的时候,我们会发现,对于x取任意的1-n中的数字,都会得到以下的余数数列:

1 2 3 4 5 ... (y-1) 0
1 2 3 4 5 ... (y-1) 0
...

可以看到,余数的出现是存在循环的,每y个数余数就完成一次循环。当然最后一个循环可能只会有几个数,构不成一个循环,所以要分开来算。

算法中有三个变量需要我们计算:

  • 循环次数
  • 满循环时符合条件的余数数量
  • 最后一个循环中符合条件的余数数量

有了这三个变量之后,我们就可以开始写对于y = i的情况,所有符合条件的x的数量。

res += (loopNum * (otherLoop > 0 ? otherLoop : 0) + (lastLoop > 0 ? lastLoop : 0));

最后把i为k-n的所有情况加总就可以得到正确解。

时间复杂度:O(N)

空间复杂度:O(1)

代码:

import java.util.Scanner;

public class NumberPair {

    public static void main(String[] args) {
        NumberPair np = new NumberPair();
        Scanner scanner = new Scanner(System.in);
        String cmd = scanner.nextLine();
        String[] cmdParams = cmd.split(" ");
        int n = Integer.parseInt(cmdParams[0]);
        int k = Integer.parseInt(cmdParams[1]);
        System.out.println(np.getNumberPair(n, k));
    }

    public long getNumberPair(int n, int k) {

        if (k == 0) return (long) n * (long) n;

        long res = 0;

        for (int i = k; i <= n; i ++) {
            /*
                n / i 表示余数的循环
                i - k + 1 表示合法的余数的数量
                n - n / i * i + 1最后一个余数循环里面最后剩下的几个余数
            */
            int lastLoop = (n - n / i * i - k + 1);
            int loopNum = (n / i);
            int otherLoop = (i - k);
//            System.out.println(i + " -> " + loopNum + " * " + otherLoop + " + " + lastLoop);
            res += (loopNum * (otherLoop > 0 ? otherLoop : 0) + (lastLoop > 0 ? lastLoop : 0));
        }

        return res;

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值