1、2019 年 8 月 8 日1素数筛选法优化邓达生原始的素数筛选法是在2,n里进行筛选。代码:void workprime(unsigned int m, unsigned int *prime, unsigned int nprime = -1;memset(mark, 0, m);for(i = 2; i 1;nprime = -1;memset(mark, 0, m);for(i = 2; i = m)break;markp |= 1;if(!(marki markp |= 2;2019 年 8 月 8 日6再删除 5 的倍数:D=7,11,13,17,19,23,29,31,而mark
2、i代表30i+1、30i+7、30i+11、30i+13、30i+17、30i+19、30i+23、30i+29 共 8 个数,刚刚一个字节可以存完,没有浪费任何空间。注:除法 “/“ 是整除,“%“运算是模运算(即求余)这样的表一共有 8 个,共有 8*8=64 项,所以我之前说过代码复杂度会提高很多。如果就想前面那样写代码的话这个函数就会很长,所以就制表来解决。代码很长,后面再列出来。为了测试上述 3 种算法的效率,我在中山大学的在线测评系统 sicily 的第一题“A-B“测试了运行效率,各自计算 33554432(225)内的素数(共 2063689 个),只删除 2 的倍数的用时大约
3、 0.9s,再删除 3 的倍数的用时大约 0.6s,再删除 5 的倍数的用时只有 0.2s!(全部代码在本机测试结果没错后再去 sicily测试时间)难道是 n 不够大?还是我的估计误差太大呢?不过由于代码复杂度都已经比较高了,而且内存空间得到充分利用(mark 的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)=30(30j+11)i+jk+11k/30)+11k%30 4i+11k/30-7k/3
4、0(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+23k/30-19k/30(30j+29)(30i+k)=30(30j+29)i+jk+29k/30)+29k%30 6i+29
5、k/30-23k/30(30(j+1)+1)(30i+k)=30(30j+31)i+jk+k)+k 2i+k-29k/302019 年 8 月 8 日7每一项代表 8 个数,刚好一个字节 8 位二进制用完),我就不深入探讨了,有兴趣的读者可以自己算一下。下面附上代码(m = n / 30):void workprime(unsigned int m, unsigned int *prime, unsigned int static const unsigned int incs8=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
6、,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;prime0 = 2;prime1 = 3;prime2 = 5;prime3 = 7;prime4 = 11;prime5 = 13;prime6 = 17;prime7
7、= 19;prime8 = 23;primenprime = 9 = 29;memset(mark, 0, m);2019 年 8 月 8 日8for(k = 1; k = m)break; else markp |= marksk0;if(p += incsk1) = m)break; else markp |= marksk1;if(p += incsk2) = m)break; else markp |= marksk2;if(p += incsk3) = m)break; else markp |= marksk3;if(p += incsk4) = m)break; else mar
8、kp |= marksk4;if(p += incsk5) = m)break; else markp |= marksk5;if(p += incsk6) = m)break; else markp |= marksk6;if(p += incsk7) = m)break; else markp |= marksk7;for(i = 1; i = m)break; else markp |= marksk0;if(p += i4 + incsk1) = m)break; else markp |= marksk1;if(p += i2 + incsk2) = m)break; else ma
9、rkp |= marksk2;if(p += i4 + incsk3) = m)break; else markp |= marksk3;if(p += i2 + incsk4) = m)break; else markp |= marksk4;if(p += i4 + incsk5) = m)break; else markp |= marksk5;if(p += i6 + incsk6) = m)break; else markp |= marksk6;if(p += i2 + incsk7) = m)break; else markp |= marksk7;2019 年 8 月 8 日9
10、对于标记 i 的倍数 ji 为合数时,只需要从 j=i,即 i2开始标记,因为对于 j= m)break; else markp |= marksk0;if(p += incsk1) = m)break; else markp |= marksk1;if(p += incsk2) = m)break; else markp |= marksk2;if(p += incsk3) = m)break; else markp |= marksk3;if(p += incsk4) = m)break; else markp |= marksk4;if(p += incsk5) = m)break; e
11、lse markp |= marksk5;if(p += incsk6) = m)break; else markp |= marksk6;if(p += incsk7) = m)break; else markp |= marksk7;for(i = 1; i = m)continue;for(markp |= marksk7;)if(p += i6 + incsk0) = m)break; else markp |= marksk0;if(p += i4 + incsk1) = m)break; else markp |= marksk1;if(p += i2 + incsk2) = m)
12、break; else markp |= marksk2;if(p += i4 + incsk3) = m)break; else markp |= marksk3;if(p += i2 + incsk4) = m)break; else markp |= marksk4;if(p += i4 + incsk5) = m)break; else markp |= marksk5;if(p += i6 + incsk6) = m)break; else markp |= marksk6;if(p += i2 + incsk7) = m)break; else markp |= marksk7;for(; i m; +i)i6 = (i2 = i 1) + (i4 = i 2);i30 = (i 5) - i2;for(k = 0; k 8; +k)if(!(marki ;return nprime;(对这篇文章有什么建议或问题可发邮件到 ,谢谢)