【问题标题】:Euler Totient: OptimizationEuler Totient:优化
【发布时间】:2013-11-01 12:36:00
【问题描述】:
int main(void)
{
  int n, div, a, b;
  double phi;
  printf("Enter n:\n");
  if (scanf("%d", &n) < 1 || n <= 0)
  {
    printf("Wrong input.\n");
    return 1;
  }

  a = n;
  div = 2;
  phi = n;

  while (n != 1)
  {
    if (n % div != 0)
      div++;
    else
    {
      n = n / div;
      if (b != div)
      {
        b = div;
        phi = phi * (1.0 - 1.0 / div);
      }
    }
  }

  printf("phi(%d) = %.f\n", a, phi);

  return 0;
}

这是我作为学校作业制作的 Eulers Totient 代码。该程序似乎运行良好,但仍然很慢。请问我怎样才能让它更快?

【问题讨论】:

  • 您是否分析了代码?你知道瓶颈在哪里吗?
  • 是否应该在进入循环之前初始化b?它在被赋值之前在if(b!=div) 行中被访问。可能不是慢的原因......你能给我们一个预期与实际速度的想法吗?您是否尝试使用-O3 标志进行编译?
  • 慢有多慢?它需要多快?
  • C 中的变量不像 BASIC 中的变量——仅仅因为你没有明确地给它们一个值并不意味着它们有一个值(即它们被赋予的内存位置的内容:“无论如何孩子在学年结束时留在储物柜里的东西还在那里,直到你把它清理干净并把自己的东西放进去”)
  • 确保使用搜索:stackoverflow.com/q/1024640/149530

标签: c optimization


【解决方案1】:

首先检查div=2

之后你只需要检查奇数,所以你可以使用div += 2。这应该会将时间缩短一半。

【讨论】:

    【解决方案2】:

    我不确定是否有更好的算法,但我们可以从容易实现的目标开始:您正在测试直到 n 的所有数字以找到它的除数。这是多余的,因为从 φ(n) 的定义中我们知道我们只需要它的质因数。

    很好,有人可能会说,我们只是将线性搜索变成了超多项式问题。

    不一定。

    采用 P6 素数候选生成器:

    def P6():
        yield 2
        yield 3
        i = 5
        while True:
            yield i
            if i % 6 == 1:
                i += 2
            i += 2
    

    让我们在它之上构建一个分解函数:

    def factors(n):
        d = {}
        primes = p6()
        for p in primes:
            while n % p == 0:
                n /= p
                d[p] = d.setdefault(p, 0) + 1
            if n == 1:
                return d
    

    现在找到 φ(n) 是微不足道的。尝试在 C 中实现它并测量差异。如果您需要它更快,像 GMP 这样的库可以提供更快的因式分解例程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-14
      • 1970-01-01
      相关资源
      最近更新 更多