【问题标题】:Can I make this C program any faster?我可以让这个 C 程序更快吗?
【发布时间】:2014-03-22 20:39:41
【问题描述】:

我需要制作一个打印所有素数的程序,这是我已经完成的:

#include <stdio.h>

int main(void) {
    long long t,m,n,i,i2,i3,found;
    float p;
    scanf ("%lld" , &t);
    for (i=1;i<=t;i++) {
        scanf ("%lld%lld" , &m ,&n);
        for (i2=m;i2<=n;i2++) {
            found=0;
            for (i3=2;i3<=i2/2;i3++) {
                p=(float)i2/i3;
                p=p-i2/i3;
                if (p==0) {
                    found=1; 
                }
            }
            if ((found==0) && (i2!=1)) {
                printf ("%lld\n" , i2); 
            }
        }
        printf ("\n");
    }
    return 0;
}

我的时间限制是 6 秒,使用此代码是不可能的,m 和 n 之间的差异最大为 100000,并且 1

【问题讨论】:

  • 跳过偶数。通过除以数字的平方根而不是其一半来检查素数。
  • 你的程序是O(n^3)
  • 编写比你的算法慢的算法将是一个挑战。网上有很多很多帖子,在 SO 和其他地方,讨论生成素数的有效方法......你有没有寻找 任何
  • 参见stackoverflow.com/a/20749428/849891 和其中的链接。
  • Prime Generator Algorithm的可能重复

标签: c primes


【解决方案1】:

有一些复杂的数学算法,例如 Sieve of Atkin,可以非常快速地找到素数,但为了您的目的,请考虑:

如果因式分解得足够远,每个非质数都可以被质数分解。

如果你已经达到 sqrt(n) 并且仍然没有发现它是可因式分解的,那么它就不会是可因式分解的,因为任何大于 sqrt(n) 的数字都必须与小于 sqrt 的数字一起因式分解(n) 达到您正在寻找的数字。

所以测试从 2 到 sqrt(n) 的每个素数,看看你的 n 是否是素数。如果 2 和 sqrt(n) 之间的素数都不是 n 的因数,则 n 一定是素数。

这应该符合您作业的速度要求。

【讨论】:

  • 他必须生成 100,000 个整数范围内的所有素数,所以筛子是唯一的方法。阿特金筛子会起作用,但有更简单的筛子。 en.wikipedia.org/wiki/Prime_number_sieve
  • 筛子不是唯一的出路。我用我的算法在不到 10 秒的时间内生成了从 2 到 10^12 的每个素数。我确信从 2 到 10^6 的素数会快得多
  • "2 to 10^6" -- 这不相关。问题是在 10^9 以下的 any 10^5 窗口中生成素数。我认为阿特金筛特别适用于音程,但也有一些 Demosthenes 筛的变体也很好。
  • @JimBalter 实际上,问题在于 10^10 以下的任何 10^6 窗口。我相信您知道,我的算法所花费的大部分时间都在最终指数上。我仍然相信,在给定参数的情况下,我的算法仍将在适当的时间内执行。
  • 我的原件是天真地复制了我回复的评论中的数字——我错误地认为你正确使用了 OP 的数字。我很快进行了编辑——之前我写了“我做对了”。无论如何,10^6 和 10^10 或 10^12 都是错误的。
【解决方案2】:

对于这个问题,约束(范围)非常大,所以最好使用Miller–Rabin primality test method


我改变了主意。您可以使用Sieve of Eratosthenes 算法。

Here 是通过埃拉托色尼筛法找到小于或等于给定整数n 的所有素数的步骤:

  • 首先创建一个从2n 的连续整数数组:(2, 3, 4, ..., n)。
  • 设 p 为整数变量,用第一个素数 2 对其进行初始化。
  • 从 p 开始,以 p 为增量向上计数,并划掉所有小于或等于 n (2p, 3p, 4p .... kp &lt;= n) 的 p 倍数。
  • 在未交叉的数组中取第一个大于 p 的数字。如果没有这样的号码&lt;= n,则停止。否则,在p(下一个素数)中分配这个新数字,然后从第 3 步开始。

【讨论】:

  • 该测试中的强骗子的熵不会对时间限制造成潜在的问题吗?
  • @ciphermagi;我不知道。
猜你喜欢
  • 2017-11-06
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 2013-11-02
  • 2016-07-12
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
相关资源
最近更新 更多