使用二进制搜索

时间:2015-08-27 12:09:08

标签: algorithm data-structures number-theory

我已经给出了一个范围 L到R 。我必须找出L到R之间有多少个数字,以便数字具有奇数个除数

1<L<R<10^18

由于L和R非常高,因此循环简单会导致超时 我发现二进制搜索可用于解决此问题。

我无法理解二元搜索如何帮助查找具有奇数的数字的数字除数。

代码:

int find (long long n) {
    int low,high,mid;
    long long v1,v2;
    low = 1;
    high = 1e9 + 1;
    if (n == 0) {
        return 0;
    }
    while (low <= high) {
        mid = (low + high) / 2;
        v1 = mid * 1LL * mid;
        v2 = (mid + 1) * 1LL * (mid + 1);
        if (v1 <= n) {
            if (v2 > n) {
                return mid;
            } else {
                low = mid + 1;
            }
        } else {
            high = mid - 1;
        }
    }
}


答案:ans = find(r) - find(l - 1); 请在数论中解释二元搜索的概念

2 个答案:

答案 0 :(得分:3)

该算法基于一个简单的事实,即为了得到奇数个除数,数n必须是一个完整的正方形。否则,对于每个除数k,还有另一个不同的除数n/k,所以你总是会有偶数除数。此算法只计算1和提供的n(包括)之间的整数平方数,实际上是integer square rootfloor(sqrt(n)))。所以它使用二进制搜索找到平方根。如果您的平台/语言上的sqrt(n)方法足够精确,您可以像这样解决问题:

ans = floor(sqrt(r)) - floor(sqrt(l-1));

通常double类型没有提供足够的精度,因此结果可能少一个或多一个。可能这就是使用二进制搜索的原因。不过,你仍然可以使用sqrt。只需计算之后的平方,如果需要,可以将结果调整为1(这样会快得多)。或者你可以使用牛顿方法(它会比调整时sqrt慢,但比二分搜索快得多。)

答案 1 :(得分:0)

对于数字 N ,假设 d N 的除数。然后总是有一个 N / d 的数字,它可以划分 N 。 只有在某些情况下d = (N/d)

时,数字才有奇数个除数

实施例: 如果N = 16

如果除数d=1N/d = 16

如果除数d=2N/d = 8

如果除数d=4N/d = 4

所以,如果我们想知道 R L 之间有奇数除数的数字,我们需要知道这个范围之间的平方数是多少

小于或等于R的平方数是 = square_root(R)

小于的平方数(以L为代表)L是 = square_root(L-1)

So answer = floor(square_root(R))-floor(square_root(L-1))

由于我们只需要整数部分,所以我们采取行动。