首页
社区
课程
招聘
[推荐]筛法,时间复杂度为O(n)
发表于: 2010-6-5 13:14 6776

[推荐]筛法,时间复杂度为O(n)

2010-6-5 13:14
6776
这里的筛法是说寻找从1到N的所有素数的筛法。不是陈景润先生的那个。。。

过程:
这两天在逛ACM相关的论坛,发现2007年复旦的xreborner大牛就把筛法改进成线性的时间复杂度了。真是可怕。不知道大家都了解过没,现在介绍给大家。

自己理解了一下,不过觉得与其用文字来表达不如上程序。

想想当初找素数,从2到N每个数字num验证,后来老师告诉我们验证可以只到sqrt(num),再后来有了筛法,再后来对2的倍数,3的倍数,6的倍数跳过。。。今天,终于有了线性的。。

程序:

//code by 冬祭
# include <stdio.h>
# include <memory.h>

# define N 20 //寻找2到N的所有素数

int main ()
{
        unsigned char P[N + 1] ; //定义一个数组标志位标识是否为素数
        unsigned int Primes[N] ; //存储素数的数组
   
        int Time = 0, Count = 0 ;//算法中的“比较次数、素数个数”

        memset (P, 1, N + 1) ;        //标志全部初始化为1
        memset (Primes, 0, N) ; //初始化素数数组

       
        for (int i = 2; i <= N; i++)
    {
                //若当前i为素数
        if (P[i])
        {
            Primes[Count++] = i ;
            Time++;        //比较一次,次数加一
        }

                //更新素数标志数组
        for (int j = 0; j < Count && i * Primes[j] <= N; j++)
        {
            P[i * Primes[j]] = 0 ;
            Time++;

            if (i % Primes[j] == 0) break;
        }

    }//end for(i)

        printf ("Time = %d\nCount = %d\n\n", Time, Count) ;

        printf ("Primes are :\t") ;
       
        for ( i = 0 ; i < Count ; i++)
                printf ("%d\t", Primes[i]) ;
       
        printf ("\n") ;

        return 0 ;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 67
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
ACM建素数表的国际惯例都这样做,不是什么新鲜的事了。

另外,我不觉得这个算法的时间复杂度是O(n)
例如:
for(int i = 0; i < n; i++) { if(1==2){;}}
请考虑上面的算法的时间复杂度。
留意一下k/Time这个系数的变化即可。
# include <stdio.h>
# include <memory.h>
#include <math.h>


#define N 60000 //寻找2到N的所有素数


int main ()
{
    unsigned char P[N + 1] ; //定义一个数组标志位标识是否为素数
    unsigned int Primes[N] ; //存储素数的数组

    int k = 2;
    for(k = 100; k < N; k += 1000)
    {
        int Time = 0, Count = 0 ;//算法中的“比较次数、素数个数”
        memset (P, 1, k + 1) ;  //标志全部初始化为1
        memset (Primes, 0, k) ; //初始化素数数组

        for (int i = 2; i <= k; i++)
        {
            //若当前i为素数      
            if (P[i])
            {
                Primes[Count++] = i ;              
            }

            //更新素数标志数组
            for (int j = 0; j < Count && i * Primes[j] <= k; j++)
            {
                P[i * Primes[j]] = 0 ;
                Time++;
                if (i % Primes[j] == 0) break;
            }

        }//end for(i)

        Time += k;
        printf ("k = %d Time = %d Count = %d\n", k, Time, Count) ;
        printf ("Time/k = %lf pai(k)/(k/lnk) = %lf\n", (double)Time / k, (Count * log((double)k)) / k);
        printf ("\n") ;
    }

    return 0 ;
} 
2010-6-5 15:28
0
雪    币: 157
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
呃不好意思。是小弟孤陋寡闻了。
2010-6-5 17:53
0
雪    币: 92
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这个筛法是近似线性。
2010-11-12 21:22
0
雪    币: 678
活跃值: (101)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
5
打表法有时候也是无奈和明智之举来的。很多时候是暴力打表出来查找规律的。
2010-11-12 21:30
0
游客
登录 | 注册 方可回帖
返回
//