线性筛法
ltl2011/06/06软件综合 IP:福建
既然有人问是否有比较高效的质数计算方法,那么我就来讲一讲吧

1. 最暴力的算法是O(n^2)的,也就是枚举一个数i在枚举2~i-1判断是否可以整除,这算法也太渣了吧………………
2. 优化一下,由于大于sqrt(i)的因子k都可以表示为i/(i/k),所以只要枚举到sqrt(i)即可,复杂度O(n^1.5)
3. 继续优化 - 筛法,枚举一个数i,将i的倍数全部筛去(用bool表记录),可以用调和级数证明时间复杂度为O(nlogn)的
4. 终极优化!筛法的缺陷在于一个数会被筛多次,造成速度偏慢,则我们只要让它被最小质因子筛掉即可。也就是程序中的这句话:if i mod Prime[j]=0 then break; 当大于最小质因子的时候(也就是第一次整除的时候)就会被掐掉,这样就使得每个数都只会被筛去一次,时间复杂度降为O(n)

鉴于提问者为Pascal选手,我就用Pascal写一个吧,0-20W的质数表大概在0.01s左右吧(开内存的时间不算……),跑10^9的质数表也很快的。希望我的讲解能对你有所帮助。


program Test;
var
    outf:text;
    n,Total,Ans,i:longint;
    Prime:array[0..30000000]of qword;
    Flag:array[0..Maxlongint shr 1]of boolean;

procedure Main;
var
    i,j:longint;
    Len:longint;
    s:string;
begin
    fillchar(Flag,sizeof(Flag),True);
    Flag[1]:=False;
    Len:=0;
    for i:=2 to n do
    begin
        if Flag[i] then
        begin
            write(outf, i,',');
            str(i,s);
            inc(Len,length(s)+1);
            if Len>150 then
            begin
                Len:=0;
                writeln(outf);
            end;
            inc(Total);
            Prime[Total]:=i;
        end;
        for j:=1 to Total do
        begin
            if Prime[j]*i<=n then Flag[i*Prime[j]]:=False
                        else break;
            if i mod Prime[j]=0 then break;
        end;
        if i mod (n div 10) = 0 then
            writeln(i div (n div 10)*10, ' %');
    end;
end;

begin
    assign(outf,'Result.txt');
    rewrite(outf);
    readln(n);
    Main;
    writeln(outf);
    writeln(outf, Total);
    close(outf);
end.
来自:计算机科学 / 软件综合
26
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
ltl 作者
13年0个月前 IP:未同步
298648
顺便说一下……其实我这个程序如果跑1亿以内的质数表大部分时间都在开内存的说……实际上线性筛法的部分非常快的……

运行者请做好心理准备……鄙人是按照Free Pascal的寻址上限开的……内存不够的请自重……可以改小一点……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
298650
话说我将10亿内的质数表打出来后有400+MB……至今没成功打开过……用记事本直接没救……用写字板要30min才能开完,而且滚动条几乎拖不动……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
拔刀斋
13年0个月前 IP:未同步
298651
试试UltraEdit32
引用第2楼ltl于2011-06-06 21:09发表的  :
话说我将10亿内的质数表打出来后有400+MB……至今没成功打开过……用记事本直接没救……用写字板要30min才能开完,而且滚动条几乎拖不动……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
298653
照样杯具……EditPlus也一样……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
zhaokenb
13年0个月前 IP:未同步
298654
[s:241] 为什么差距那么大,表示我的数学真的不行了,刚刚看了10分钟终于看明白了,好强大的方法!!!!!!!
我原来一直陷在枚举法里了,只是简单的优化了而已
PS:其实我的pascal真不怎么样,我只是小学的时候把小学那本给学完了,我还是学习一下LZ的思路吧,然后搞成VB的,毕竟VB学的深入一些
在此多谢LZ了[s:234]
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金星凌日
13年0个月前 IP:未同步
298657
用WinHex打開數GB的文件都沒有問題,可以正常顯示。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
298658
引用第5楼zhaokenb于2011-06-06 21:26发表的  :
[s:241] 为什么差距那么大,表示我的数学真的不行了,刚刚看了10分钟终于看明白了,好强大的方法!!!!!!!
我原来一直陷在枚举法里了,只是简单的优化了而已
PS:其实我的pascal真不怎么样,我只是小学的时候把小学那本给学完了,我还是学习一下LZ的思路吧,然后搞成VB的,毕竟VB学的深入一些
在此多谢LZ了[s:234]

我Pascal也是五年级学的……初一学了C++不过用的少,到高中才转C++的

P.S.:我讨厌VB这种SB语言……实在不知道中国教育部是怎么想的,为什么会让高中信息课教VB……自从四年级因为好奇学了VB之后就觉得各种SB…………虽然作为OIer表示从小就不去上电脑课……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc
13年0个月前 IP:未同步
298676
用pascal的表示筛法毫无压力
pascal装机自带快排、筛素数等各种标程
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金星凌日
13年0个月前 IP:未同步
298688
回 7楼(ltl) 的帖子
VB其實並不SB。到目前爲止我沒發現VB做不到而其他語言能做到的事情(寫操作系統除外)。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
hefanghua
13年0个月前 IP:未同步
298697
回 6楼(金星凌日) 的帖子
是个好办法。如果把ASCII码的结果改为二进制则运算和打开会再快点。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
298699
引用第8楼ltc于2011-06-06 22:32发表的  :
用pascal的表示筛法毫无压力
pascal装机自带快排、筛素数等各种标程

赛场上是没有的

C++选手表示stl才是王道……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc
13年0个月前 IP:未同步
298788
引用第11楼ltl于2011-06-06 23:37发表的 :

赛场上是没有的

C++选手表示stl才是王道……  

很遗憾,赛场上有
我至今不会背qsort就因为可以直接抄
不信的自己打开安装目录,搜索qsort.pp
具体目录是FPC\\2.2.4\\demo\\text
如果是别的版本就把2.2.4改掉
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
298796
我们这里是删掉的
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
featherwit
13年0个月前 IP:未同步
298815
引用第4楼ltl于2011-06-06 21:26发表的  :
照样杯具……EditPlus也一样……


去用vim吧,windows下有gvim~比这两个靠谱多了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
featherwit
13年0个月前 IP:未同步
298817
引用第5楼zhaokenb于2011-06-06 21:26发表的  :
[s:241] 为什么差距那么大,表示我的数学真的不行了,刚刚看了10分钟终于看明白了,好强大的方法!!!!!!!
我原来一直陷在枚举法里了,只是简单的优化了而已
PS:其实我的pascal真不怎么样,我只是小学的时候把小学那本给学完了,我还是学习一下LZ的思路吧,然后搞成VB的,毕竟VB学的深入一些
在此多谢LZ了[s:234]


话说...你应该多补充一些基础知识,跟他这种搞竞赛的选手在算法方面是没得比的~~。
埃托拉斯筛法是很著名的求素数算法...。

当然,你要真想搞的话,要看的书就多了...
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
299007
引用第15楼featherwit于2011-06-07 14:22发表的  :


话说...你应该多补充一些基础知识,跟他这种搞竞赛的选手在算法方面是没得比的~~。
埃托拉斯筛法是很著名的求素数算法...。

.......

无论搞不搞竞赛……《算法导论》还是都要看一下比较好
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc
13年0个月前 IP:未同步
299015
引用第16楼ltl于2011-06-08 12:37发表的 :

无论搞不搞竞赛……《算法导论》还是都要看一下比较好  

算法导论难度还是很大的
除了最开头的就没看懂过
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
299020
引用第17楼ltc于2011-06-08 13:17发表的  :

算法导论难度还是很大的
除了最开头的就没看懂过


难度是有,但是要学啊,毕竟那个是算法的基础(当然,还有很多地方过于高深,比较数学化的算法看不懂),除了算导上的算法外还有很多别的算法要学的
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn
13年0个月前 IP:未同步
299067
打不开txt?用Ramdisk整个虚拟盘(前提是有多的内存),存进去,就OK了。。。要不直接输出到屏幕上去,不过进程可能会挂。
其实两位可以比下不同语言不同编译器的效率。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
299108
效率应该是C++快吧……至少C++是远比Pascal好的,VB我觉得比Pascal还悲剧啊……

400+MB的txt不是那么好开的……
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc
13年0个月前 IP:未同步
299125
不过这么大的读写就不一定了
据说pascal的读写比c++快很多
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
299153
C++也有很快的读写方式,只是一般用不到,而且比较麻烦
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
featherwit
13年0个月前 IP:未同步
299399
C的话,可以考虑用memfile来做读写,然后你需要考虑的事情就少了~
而C++的文件流本身效率就不高。
话说处理几个G的log文件是常事儿~

另外还是强力向你推荐vim,习惯了很有好处的。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltl作者
13年0个月前 IP:未同步
299603
我在赛场上没找到vim……基本都是Gedit&g++&GUIDE(一个北航写的诡异的IDE……)
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
alaxn
12年8个月前 IP:未同步
328767
我记得质数的判断,有一个Miller Rabbin测试素数
速度会不会快一点啊?
不过这个是概率型
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
ltl
学者 笔友
文章
50
回复
3650
学术分
2
2009/09/27注册,2个月19天前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}