1 #include<iostream> 2 using namespace std; 3 const long N = 200000; 4 long prime[N] = {0}, num_prime = 0; 5 int isNotPrime[N] = {1,1}; 6 int main() { 7 for(long i = 2; i < N; ++i) { 8 if(!isNotPrime[i]) 9 prime[num_prime++] = i; 10 for(long j = 0; j < num_prime && i*prime[j] < N; ++j) { 11 isNotPrime[i*prime[j]] = 1; 12 if(! (i % prime[j]) )//qwqwqwqwqwqwq 13 break; 14 } 15 } 16 return 0; 17 }
注意到代码中赤黑色的记号了吗?
代码中其他的东西我都懂,这是个什么玩意?
本文撰写的目的就是帮助理解这个记号所标记的那一行~
除了线性筛法,我还接触过其他的筛法,当然都不是线性的,就算是线性筛法也不是绝对线性的。
正文开始前,先思考一个问题:为什么线性筛法是最优秀的?
答:对于单个数的筛除动作没有重复多次。
这就是线性筛法的“核心”了~
于是?
既然某些基于约数设计的算法无法简单地得到更有效的优化了,
从被筛数本身来考虑,说不定能另辟蹊径。
被筛数是合数,设为S。
于是这个合数有两个或以上的质因子,S = p(质因子) * K(K是某一个数)。
当然 p 、 K 的组合可以是多种多样的。
当S较大时, K是一个合数,于是K也可以拆分成 a*b的形式(a是质数, b嘛……不知道qwq),
S就可以写成这样:p * a * b。
a、b的大小有差别时, 某些规律就被呈现出来了:
一个合数与一个质数的乘积可以表示成一个更大的合数与一个更小的质数之积。
这个规律如何应用到质数的筛法上呢?
可以将这个规律的“唯一性”应用到质数的筛法上,
即每个较大合数都以这个规律中呈现的“唯一的最小质因子分解状态”被筛去。
现在再看代码中的“红色行”,
感觉仍然迷茫,代码的意思是:
质数会与之前的所有质数组合,筛除合数,
而合数与质数的组合却被限制,合数最多只能和自己的最小质因子及更小者组合?
为什么呢?
如果当前数是素数,显然之前数所筛除的数中都没有“当前数”这个质因子,与之前不会重复。
当前数是合数,被筛除的合数只会被以“最小态”筛除,一定不会重复,也一定不会被漏掉。
为什么不会被漏掉呢?<N的数的约数一定小于N。
为什么一定不会重复呢?
直观地理解:
设被筛的数是 S:p1*p2*p3,p1<p2<p3。
既然保证当前数与质数的组合被限制, 就不会出现如下的情况 : S以 p3*p2*p1的形式删去。
更直观地,S的若干 质数*合数 的组合中, 只有其中唯一的一种, 即“最小态”会被生成。
于是线性筛法就这样很好地减少了操作的冗余度。
标签:prime,筛法,合数,理解,筛除,线性,质数 来源: https://www.cnblogs.com/tztqwq/p/10875928.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。