C 求n个素数与所有前素数试除的时间复杂度

C 求n个素数与所有前素数试除的时间复杂度,c,time-complexity,big-o,primes,C,Time Complexity,Big O,Primes,问题:寻找n个素数 #include<stdio.h> #include<stdlib.h> void firstnprimes(int *a, int n){ if (n < 1){ printf("INVALID"); return; } int i = 0, j, k; // i is the primes counter for (j = 2; i != n

问题:寻找n个素数

#include<stdio.h>
#include<stdlib.h>

void firstnprimes(int *a, int n){

    if (n < 1){
        printf("INVALID");
        return;
    }

    int i = 0, j, k;                // i is the primes counter

    for (j = 2; i != n; j++){       // j is a candidate number

        for (k = 0; k < i; k++)
        {
            if (j % a[k] == 0)      // a[k] is k-th prime
                break;
        }

        if (k == i)                 // end-of-loop was reached
            a[i++] = j;             // record the i-th prime, j
    }
    return;
}

int main(){
    int n;
    scanf_s("%d",&n);
    int *a = (int *)malloc(n*sizeof(int));
    firstnprimes(a,n);
    for (int i = 0; i < n; i++)
        printf("%d\n",a[i]);
    system("pause");
    return 0;
}
#包括
#包括
第一次无效时间(整数*a,整数n){
if(n<1){
printf(“无效”);
返回;
}
int i=0,j,k;//i是素数计数器
对于(j=2;i!=n;j++){//j是一个候选数
对于(k=0;k
我的函数的内循环运行i次(最多),其中i是低于给定候选数的素数,外循环运行(第n个素数-2)次

我如何用大O表示法推导该算法的复杂性


提前感谢。

素数定理指出,渐近地,小于
n
的素数等于
n/logn
。因此,内部循环将运行
i*max
=
n/log n*n
次θ(假设
max
=
n

此外,您的外部循环以
n log n
次的顺序运行,使得
n/log n*n*n log n=n^3
的总复杂度θ。换句话说,这不是最有效的算法

注意,有更好的近似(例如,
n
-th素数更接近:

n logn+n logn-n+n logn/logn+

但是,既然你只关心大O,这个近似就足够了


此外,还有更好的算法来完成您想要做的事情。有关更多信息,请查阅伪素数主题。

在伪代码中,您的代码是

firstnprimes(n)=a[:n]#数组a的前n个条目
哪里
i=0
a=[j代表[2..]
if为_空([j表示a[:i]if(j%p==0)])
&&(++i)]
(假设短路
为空
,一旦发现列表为非空,则返回
false

它所做的是测试从2开始的每一个候选数及其前面的所有素数

Melissa O'Neill分析了该算法,并将其复杂性导出为O(n^2)

基本上,产生的n个素数中的每一个都与它前面的所有素数配对(被测试)(即k-1素数,对于k 算术级数0…(n-1)的和是(n-1)n/2,也就是O(n^2);她表明,复合项不会产生任何比总和更重要的项,因为在n的路上有 但
为空
计算提前失败


事情是这样的:当m=n log n时,将有m/2个偶数,对于每个偶数,
为空
计算只需1步;m/3乘以3分2步;m/5分3步;等等

因此,通过不处理多重性(高估了),复合材料的总贡献是:

SUM{i=1,…,n}(im/p_i)//p_i是第i个素数
=m和{i=1,…,n}(i/p_i)
=n log(n)和{i=1,…,n}(i/p_i)
14000
=n^2

这个不等式可以在as
Sum[i/Prime[i],{i,14000}]Log[14000.0]/14000.0
上测试(它是0.99921,随着n的增大而减小,在0.963554处测试到n=2000000).

旁白:您不需要检查所有以前的素数作为因子-仅检查那些…除了
2
这是唯一的偶数素数。因此,使用
2
初始化数组后,外循环可以
for(j=3;i!=n;j+=2)
我的意思是我的内部循环最多运行I次。谢谢。我们可以简化查找n个素数的代码吗?用什么语言?C?--简化或优化以提高其速度?后者将需要更复杂的代码(添加一个或两个新测试).或者算法可能会完全改变,特别是从您的试用版改为。在这方面有很多问答。
SUM{i = 1, ..., n} (i m / p_i)          // p_i is the i-th prime
= m SUM{i = 1, ..., n} (i / p_i)
= n log(n) SUM{i = 1, ..., n} (i / p_i)
< n log(n) (n / log(n))                 // for n > 14,000 
= n^2