ImageVerifierCode 换一换
格式:DOC , 页数:10 ,大小:263KB ,
资源ID:7238343      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/7238343.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(素数筛选法优化_2.doc)为本站上传会员【pc****0】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

素数筛选法优化_2.doc

1、2024年12月25日 素数筛选法优化 邓达生 原始的素数筛选法是在{2,……,n}里进行筛选。代码: void workprime(unsigned int m, unsigned int *prime, unsigned int &nprime, char *mark){ unsigned int i, p; nprime = -1; memset(mark, 0, m); for(i = 2; i < m; ++i) if(!mark[i]) for(p = (prime[++nprime] = i) + i; p < m; p += i)

2、 mark[p] = 1; } } (注:本文章的代码都不进行for循环优化,例如上述代码改为 void workprime(unsigned int m, unsigned int *prime, unsigned int &nprime, char *mark){ unsigned int i, p, m2 = m >> 1; nprime = -1; memset(mark, 0, m); for(i = 2; i <= m2; ++i) if(!mark[i]) for(p = (prime[++nprime] = i) + i; p

3、< m; p += i) mark[p] = 1; for(; i < m; ++i) if(!mark[i]) prime[++nprime] = i; } 若要优化请自行优化) 本文章的优化仅仅是加快筛选的速度(因为基础都是筛选),如果原算法时间和空间复杂度是f(n)和g(n),则优化后为k1f(n)和k2g(n),k1、k2<1。 优化: 因为2是已知的素数,所以{2,……,N}里的所有偶数(2的倍数)都可以在筛选前排除,也就是说待筛选列表里不应该存在2的倍数,并且在筛选中不应该存在检测2的倍数是否素数的行为或者将2的倍数标记为合数的行为,例

4、如当检测到3是素数后,要把3的倍数都标记为合数时,不应该把6标记为合数,因为在待筛选列表里没有6。 我的基本思想就是在原始的待筛选列表里删除某(几)个已知素数的倍数。设删除后的待筛选列表为D,很容易证明若x、kx∈D,则k∈D。证明:若k∉D,则k是某个已知素数的倍数,则kx是某个已知素数的倍数,所以kx∉D,与已知kx∈D矛盾,所以k∈D。 现在原始待筛选列表删除2的倍数(即D={3,5,7,9……}),对于标记数组mark[],mark[i]代表的就已经不能是i了,mark[i]代表的是2i+1是否合数。 筛选过程:假设现在mark[i]是false,代表2i+1是素数。然后就要把2

5、i+1的倍数都标记为合数。应该被标记为合数的数分别是 应标记的数/2i+1的倍数 对应mark的下标 3(2i+1)=2(3i+1)+1 3i+1 5(2i+1)=2(5i+2)+1 5i+2 7(2i+1)=2(7i+3)+1 7i+3 …… …… (2k+1)(2i+1)=2((2k+1)i+k)+1 (2k+1)i+k 所以待标记的数的下标初始值为3i+1,增量为2i+1. 算法代码如下(m = n / 2):void workprime(unsigned int m, unsigned int *prime, unsigned int &nprime

6、 char *mark){ unsigned int i, j, p; prime[nprime = 0] = 2; memset(mark, 0, m); for(i = 1; i < m; ++i) if(!mark[i]) for(p = (prime[++nprime] = j = (i << 1) + 1) + i; p < m; p += j) mark[p] = 1; } 对于求n以内的素数,原始算法m=n,标记合数for循环增量是i,优化后的算法m=n/2,标记合数for循环增量是2i+1,效率提高大约一倍。 继续优化:原

7、始待筛选列表删除2的倍数后m=n/2,再删除3的倍数后m=n*(2/6)=n/3,删除5的倍数后m=n*(8/30)=4n/15,……可以看出来,到后面即使再优化,效率也不会提高多少,而其后可以看到,效率在以很小的幅度提高时,代码的复杂度却以很高的速度提高。(以上为个人简单估计) 再删除3的倍数:D={5,7,11,13,17,19……} 令mark[i]代表6i±1是否合数。char类型是1字节8位,用低两位来标记(0位代表6i-1,1位代表6i+1)。 6i-1的倍数 mark下标 mark下标增量 位 6i-1 i 0 5(6i-1)=30i-5=6(5i-1

8、)+1 5i-1 4i-1 1 7(6i-1)=42i-7=6(7i-1)-1 7i-1 2i 0 11(6i-1)=66i-11=6(11i-2)+1 11i-2 4i-1 1 13(6i-1)=78i-13=6(13i-2)-1 13i-2 2i 0 …… …… …… …… (6j-1)(6i-1)=6((6j-1)i-j)+1 (6j-1)i-j 4i-1 1 (6j+1)(6i-1)=6((6j+1)i-j)-1 (6j+1)i-j 2i 0 6i+1的倍数 mark下标 mark下标增量 位 6i+1 i 1

9、 5(6i+1)=30i+5=6(5i+1)-1 5i+1 4i+1 0 7(6i+1)=42i+7=6(7i+1)+1 7i+1 2i 1 11(6i+1)=66i+11=6(11i+2)-1 11i+2 4i+1 0 13(6i+1)=78i+13=6(13i+2)+1 13i+2 2i 1 …… …… …… …… (6j-1)(6i+1)=6((6j-1)i+j)-1 (6j-1)i+j 4i+1 0 (6j+1)(6i+1)=6((6j+1)i+j)+1 (6j+1)i+j 2i 1 最终算法代码(m = n / 6):void

10、 workprime(unsigned int m, unsigned int *prime, unsigned int &nprime, char *mark){ unsigned int i, j1, j2, p; prime[0] = 2; prime[nprime = 1] = 3; memset(mark, 0, m); for(i = 1; i < m; ++i){ if(!(mark[i] & 1)){ prime[++nprime] = (j1 = (i << 2) - 1) + (j2 = i << 1); for(p = i + j

11、1; p < m; p += j1){ mark[p] |= 2; if((p += j2) >= m)break; mark[p] |= 1; } } if(!(mark[i] & 2)){ prime[++nprime] = (j1 = (i << 2) + 1) + (j2 = i << 1); for(p = i + j1; p < m; p += j1){ mark[p] |= 1; if((p += j2) >= m)break; mark[p] |= 2; }; };

12、 }; }; 再删除5的倍数:D={7,11,13,17,19,23,29,31……},而mark[i]代表30i+1、30i+7、30i+11、30i+13、30i+17、30i+19、30i+23、30i+29 共8个数,刚刚一个字节可以存完,没有浪费任何空间。 注:除法 "/" 是整除,"%"运算是模运算(即求余) 30i+k的30j+c倍数 mark下标增量 (30j+1)(30i+k)=30((30j+1)i+jk)+k (30j+7)(30i+k)=30((30j+7)i+jk+7k/30)+7k%30 6i+7k/30 (30j+11)(30i+k)

13、30((30j+11)i+jk+11k/30)+11k%30 4i+11k/30-7k/30 (30j+13)(30i+k)=30((30j+13)i+jk+13k/30)+13k%30 2i+13k/30-11k/30 (30j+17)(30i+k)=30((30j+17)i+jk+17k/30)+17k%30 4i+17k/30-13k/30 (30j+19)(30i+k)=30((30j+19)i+jk+19k/30)+19k%30 2i+19k/30-17k/30 (30j+23)(30i+k)=30((30j+23)i+jk+23k/30)+23k%30 4i+2

14、3k/30-19k/30 (30j+29)(30i+k)=30((30j+29)i+jk+29k/30)+29k%30 6i+29k/30-23k/30 (30(j+1)+1)(30i+k)=30((30j+31)i+jk+k)+k 2i+k-29k/30 这样的表一共有8个,共有8*8=64项,所以我之前说过代码复杂度会提高很多。如果就想前面那样写代码的话这个函数就会很长,所以就制表来解决。 代码很长,后面再列出来。为了测试上述3种算法的效率,我在中山大学的在线测评系统sicily的第一题"A-B"测试了运行效率,各自计算33554432(225)内的素数(共2063689个),

15、只删除2的倍数的用时大约0.9s,再删除3的倍数的用时大约0.6s,再删除5的倍数的用时只有0.2s!(全部代码在本机测试结果没错后再去sicily测试时间)难道是n不够大?还是我的估计误差太大呢?不过由于代码复杂度都已经比较高了,而且内存空间得到充分利用(mark的每一项代表8个数,刚好一个字节8位二进制用完),我就不深入探讨了,有兴趣的读者可以自己算一下。下面附上代码(m = n / 30): void workprime(unsigned int m, unsigned int *prime, unsigned int &nprime, char *mark){ static

16、const char marks[][8]={ 2,4,8,16,32,64,128,1, 32,16,1,128,8,4,64,2, 16,1,64,2,128,8,32,4, 1,64,32,4,2,128,16,8, 128,2,4,32,64,1,8,16, 8,128,2,64,1,16,4,32, 4,8,128,1,16,32,2,64, 64,32,16,8,4,2,1,128}; static const unsigned int incs[][8]={ 0,0,0,0,0,0,0,1, 1,1,1,0,1,1,

17、1,1, 2,2,0,2,0,2,2,1, 3,1,1,2,1,1,3,1, 3,3,1,2,1,3,3,1, 4,2,2,2,2,2,4,1, 5,3,1,4,1,3,5,1, 6,4,2,4,2,4,6,1}; static const unsigned int base[]={1,7,11,13,17,19,23,29}; static const char basemark[]={1,2,4,8,16,32,64,128}; unsigned int i, i2, i4, i6, i30, p, j, k; prime[0] = 2;

18、 prime[1] = 3; prime[2] = 5; prime[3] = 7; prime[4] = 11; prime[5] = 13; prime[6] = 17; prime[7] = 19; prime[8] = 23; prime[nprime = 9] = 29; memset(mark, 0, m); for(k = 1; k < 8; ++k) // 标记 7、11、13、17、19、23、29 的倍数为合数(即 i = 0) for(p = 0;;){ if((p += incs[k][0]) >= m)br

19、eak; else mark[p] |= marks[k][0]; if((p += incs[k][1]) >= m)break; else mark[p] |= marks[k][1]; if((p += incs[k][2]) >= m)break; else mark[p] |= marks[k][2]; if((p += incs[k][3]) >= m)break; else mark[p] |= marks[k][3]; if((p += incs[k][4]) >= m)break; else mark[p] |= marks[k][4];

20、 if((p += incs[k][5]) >= m)break; else mark[p] |= marks[k][5]; if((p += incs[k][6]) >= m)break; else mark[p] |= marks[k][6]; if((p += incs[k][7]) >= m)break; else mark[p] |= marks[k][7]; }; for(i = 1; i < m; ++i){ i6 = (i2 = i << 1) + (i4 = i << 2); i30 = (i << 5) - i2; for(k

21、 0; k < 8; ++k) if(!(mark[i] & basemark[k])){ prime[++nprime] = i30 + base[k]; for(p = i;;){ if((p += i6 + incs[k][0]) >= m)break; else mark[p] |= marks[k][0]; if((p += i4 + incs[k][1]) >= m)break; else mark[p] |= marks[k][1]; if((p += i2 + incs[k][2]) >= m)break; el

22、se mark[p] |= marks[k][2]; if((p += i4 + incs[k][3]) >= m)break; else mark[p] |= marks[k][3]; if((p += i2 + incs[k][4]) >= m)break; else mark[p] |= marks[k][4]; if((p += i4 + incs[k][5]) >= m)break; else mark[p] |= marks[k][5]; if((p += i6 + incs[k][6]) >= m)break; else mark[

23、p] |= marks[k][6]; if((p += i2 + incs[k][7]) >= m)break; else mark[p] |= marks[k][7]; }; }; }; }; 对于标记i的倍数ji为合数时,只需要从j=i,即i2开始标记,因为对于j

24、t *prime, char *mark){ unsigned int nprime; static const char marks[][8]={ 2,4,8,16,32,64,128,1, 32,16,1,128,8,4,64,2, 16,1,64,2,128,8,32,4, 1,64,32,4,2,128,16,8, 128,2,4,32,64,1,8,16, 8,128,2,64,1,16,4,32, 4,8,128,1,16,32,2,64, 64,32,16,8,4,2,1,128 }; static const un

25、signed int incs[][8]={ 0,0,0,0,0,0,0,1, 1,1,1,0,1,1,1,1, 2,2,0,2,0,2,2,1, 3,1,1,2,1,1,3,1, 3,3,1,2,1,3,3,1, 4,2,2,2,2,2,4,1, 5,3,1,4,1,3,5,1, 6,4,2,4,2,4,6,1 }; static const unsigned int base[]={1,7,11,13,17,19,23,29}; static const char basemark[]={1,2,4,8,16,32,64,128}

26、 unsigned int i, i2, i4, i6, i30, p, k, m2 = 1 + (int)sqrt(m / 30.0); prime[0] = 2; prime[1] = 3; prime[2] = 5; prime[3] = 7; prime[4] = 11; prime[5] = 13; prime[6] = 17; prime[7] = 19; prime[8] = 23; prime[nprime = 9] = 29; memset(mark, 0, m); for(k = 1; k < 8; ++k)

27、for(p = 0;;){ if((p += incs[k][0]) >= m)break; else mark[p] |= marks[k][0]; if((p += incs[k][1]) >= m)break; else mark[p] |= marks[k][1]; if((p += incs[k][2]) >= m)break; else mark[p] |= marks[k][2]; if((p += incs[k][3]) >= m)break; else mark[p] |= marks[k][3]; if((p += incs[k][4

28、]) >= m)break; else mark[p] |= marks[k][4]; if((p += incs[k][5]) >= m)break; else mark[p] |= marks[k][5]; if((p += incs[k][6]) >= m)break; else mark[p] |= marks[k][6]; if((p += incs[k][7]) >= m)break; else mark[p] |= marks[k][7]; }; for(i = 1; i <= m2; ++i){ i6 = (i2 = i << 1) +

29、i4 = i << 2); i30 = (i << 5) - i2; for(k = 0; k < 8; ++k) if(!(mark[i] & basemark[k])){ prime[++nprime] = i30 + base[k]; if((p = (i30 + 1) * i + base[k] * i) >= m)continue; for(mark[p] |= marks[k][7];;){ if((p += i6 + incs[k][0]) >= m)break; else mark[p] |= marks[k][0

30、]; if((p += i4 + incs[k][1]) >= m)break; else mark[p] |= marks[k][1]; if((p += i2 + incs[k][2]) >= m)break; else mark[p] |= marks[k][2]; if((p += i4 + incs[k][3]) >= m)break; else mark[p] |= marks[k][3]; if((p += i2 + incs[k][4]) >= m)break; else mark[p] |= marks[k][4];

31、 if((p += i4 + incs[k][5]) >= m)break; else mark[p] |= marks[k][5]; if((p += i6 + incs[k][6]) >= m)break; else mark[p] |= marks[k][6]; if((p += i2 + incs[k][7]) >= m)break; else mark[p] |= marks[k][7]; }; }; }; for(; i < m; ++i){ i6 = (i2 = i << 1) + (i4 = i << 2); i30 = (i << 5) - i2; for(k = 0; k < 8; ++k) if(!(mark[i] & basemark[k])) prime[++nprime] = i30 + base[k]; }; return nprime; }; (对这篇文章有什么建议或问题可发邮件到,谢谢) 10

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服