【问题标题】:Fastest way to find prime factors after sieve筛后找出素因数的最快方法
【发布时间】:2015-10-05 15:53:46
【问题描述】:

sieve 之后,我已将所有素数存储在向量primes 中的某个范围内。现在我想在短时间内找到n的所有质因数。

我的代码:

    i=0
    while(primes[i]<=n)
    {
        if(n%primes[i]==0)
        {
           cout<<primes[i]<<endl;
        }
        while(n%primes[i]==0)
            n/=primes[i];
        i++;
    }

但这不是有效的,请提出任何可能的修改。 谢谢!

【问题讨论】:

    标签: performance time-complexity primes sieve-of-eratosthenes factorization


    【解决方案1】:

    我认为这应该更有效,因为我正在消除代码中的另一个循环。我在 C# 中对此进行了测试,但我使用硬编码数字对其进行了测试。

    我认为这是您想看到的代码。希望它更有效率。我用 C# 编写它并且没有素数列表,所以我硬编码(或者对于我的示例来说足够了)

    我认为可以根据您的代码工作的代码

    i = 0
    while(n > 1)
    {
        if(n % primes[i] == 0)
        {
           cout<<primes[i]<<endl;
           n /= primes[i];
        }
        else
            i++;
    }
    

    我用 C# 编写的代码模仿了您的代码,或者至少模仿了您正在做的事情。

            int n = 1806046;
            int[] primes;
            primes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 439, 601, 733, 941, 1151 };
            int i = 0;
            while (n > 1)
            {
                if (n % primes[i] == 0)
                {
                    comboBox1.Items.Add(primes[i]);
                    n /= primes[i];
                }
                else
                    i++;
            }
    

    这是我在 C# 中测试并基于它的代码。效果很好并且迭代了所有数字而不仅仅是素数。

            int x = 1806046;
            int i = 2;
    
            while (x > 1)
            {
                if (x % i++ == 0)
                {
                    x /= --i;
                }
            }
    

    【讨论】:

    • 其实几乎是一样的时间。
    • 哦,伙计,这需要多快?你还在用 C 编码吗?
    • 我正在使用 c++,在一个文件中大约有 10^7 个数字,并且数字的限制是从 1
    • 您是否尝试过使用条件运算符? (n % primes[i] == 0)?(n /= primes[i]):(i++) 我想我记得它在运行时在机器代码中少用了一两行。我不知道这是否会提升任何性能,但现在值得一试。
    • 这里有一些算法,如果你想试一试,它们很可能会更快。它们是用 python 编写的,但是从 Python 到 C++ 的转换应该不会太痛苦。祝你好运,我希望这些帮助! comeoncodeon.wordpress.com/2010/09/18/…
    【解决方案2】:

    您正在检查直到n 的所有素数。你不需要这样做。一旦你删除了所有因素,包括sqrt(n),那么剩余的未分解部分本身就是质数或者它是 1。

    您可以在n == 1 时退出外循环,因为没有更多的质因数可以找到。想象一个像 16 这样的数字,它有很多小的质因数。

    您每次都通过外循环进入内循环。你不需要这样做;当您的if 为真时,您只需要内部循环。

    进入if 后,您可以通过将while 循环更改为do 循环来节省重复模数计算。

    i = 0;
    
    // Find prime factors up to square root.
    limit = sqrt(n);
    while ((primes[i] <= limit) && (n > 1))
    {
        if (n % primes[i] == 0)
        {
           cout << primes[i] << endl;
           do 
           {
               n /= primes[i];
           } while (n % primes[i] == 0);
        }
        i++;
    }
    
    // Find possible factor above square root.
    if (n > 1) 
    {
        cout << n << endl;
    }
    

    我没有测试过代码,所以最好自己测试一下。

    【讨论】:

    • IMO 这是一个快速循环结构。一大改进是在 while 之后重新计算 limit,但仍在 if 语句中。 n(未分解的部分)已减少,因此我们不必看得太远。
    • 我考虑过。这实际上取决于平方根计算的速度。可能最好尝试两种方式,看看在给定的机器上哪种方式更快。我也觉得cold_coder想要一个相当简单的答案,所以我决定不包括那个调整。 YMMV。
    【解决方案3】:

    解决这个问题的关键是理解只能有一个素数 >= square_root(N) 。

    因此,您可以遍历素数列表直到 square_root(N) 。您可以执行以下代码:

    Factor generation

    【讨论】:

      猜你喜欢
      • 2013-09-26
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      • 2019-07-07
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      相关资源
      最近更新 更多