你如何以有效的方式解决这种对数不等式?

时间:2011-09-17 14:07:56

标签: algorithm equation inequality

不等式是:nlogn< = a(n是自然数,log是10)。问题:n的最大值是多少?

我的解决方案是将n = 1扫描到无穷大(步骤1),直到达到nlogn>的程度。一个。返回的结果为n - 1

但是我发现当a非常大时这不是很有效。有没有人有一个好主意如何解决它?

4 个答案:

答案 0 :(得分:7)

我正确地为comestorm的解决方案做了代数并且实现了。在我的机器上,Newton的方法比二进制搜索要好4倍。我在所有非负32位整数上测试了newton()

#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <time.h>

static int newton(double a) {
    if (a < 2.0 * log10(2.0)) {
        return 1;
    } else if (a < 3.0 * log10(3.0)) {
        return 2;
    }
    double a_log_10 = a * log(10);
    double x = a / log10(a);
    x = (x + a_log_10) / (1.0 + log(x));
    x = (x + a_log_10) / (1.0 + log(x));
    double n = floor(x);
    if (n * log10(n) > a) {
        n--;
    } else if ((n + 1.0) * log10(n + 1.0) <= a) {
        n++;
    }
    return n;
}

static int binarysearch(double a) {
    double l = floor(a / log10(a));
    double u = floor(a) + 1.0;
    while (1) {
        double m = floor((l + u) / 2.0);
        if (m == l) break;
        if (m * log10(m) > a) {
            u = m;
        } else {
            l = m;
        }
    }
    return l;
}

static void benchmark(const char *name, int (*solve)(double)) {
    clock_t start = clock();
    for (int a = 1 << 22; a >= 10; a--) {
        int n = solve(a);
        assert(n * log10(n) <= a);
        assert((n + 1) * log10(n + 1) > a);
    }
    printf("%s: %.2f\n", name, (clock() - start) / (double)CLOCKS_PER_SEC);
}

int main(int argc, char *argv[]) {
    benchmark("newton", newton);
    benchmark("binarysearch", binarysearch);
}

答案 1 :(得分:5)

使用二分搜索来完成。起始间隔可以是(1,a)或(sqrt(a),a)。

答案 2 :(得分:1)

如果求解方程nlogn = a,则可以避免每次进行比较时都执行该计算。等式是Transcendental equation,因此恒定时间迭代可以得到一个相当好的近似结果。然后对您的数据执行Binary Search

procedure solve_transcendental
   n = 50
   for i = 1 .. 20
      n = a / log(n)
   end
end

答案 3 :(得分:0)

二进制搜索是一个很好的可靠答案。解决这样的方程的另一种方法是将它们重写为x = f(x)然后计算出f(x),f(f(x)),f(f(f(x)))等等,并且希望结果收敛。如果| f'(x)|,则有希望&LT; 1.重写n log n = a,因为n = a / log n似乎在实践中表现出色。