举例理解欧拉筛法
欧拉筛法的基本思想
在埃氏筛法的基础上,让每个合数只被它的最小的质因子筛选一次,以达到不重复的目的。本算法的关键就在于让每个合数只被它的最小的质因子筛选一次,记住这句话,后面会解释。
/*求小于等于n的素数的个数*/ #include<stdio.h> #include<string.h> using namespace std; int main() { int n, cnt = 0; int prime[100001];//存素数 bool vis[100001];//保证不做素数的倍数,被筛掉就使其等于1 scanf("%d", &n); memset(vis, false, sizeof(vis));//初始化 memset(prime, 0, sizeof(prime)); for(int i = 2; i <= n; i++) { if(!vis[i])//没被筛到,所以i是素数 prime[cnt++] = i;//将i加入 for(int j = 0; j<cnt && i*prime[j]<=n; j++) { vis[i*prime[j]] = true;//找到的素数的倍数不访问 if(i % prime[j] == 0) break;//关键一步!下有说明 } } printf("%d\n", cnt); return 0; }
对于visit[i*prime[j]] = 1 的理解
对每个从小到大遍历到的i,让他乘上之前已经找到的素数,将每个得到的积筛掉
对于关键一步的理解
if(i % prime[j] == 0) break;
我们以当i=8,j=1时的情况为例(自己动手在草稿纸上跟着写一遍):
- 此时prime[j]=2,prime[j+1]=3;
- 此时将 i * prime[j]= 8 * 2 =16 筛去(16=2*8=4*4,此时16被他最小的质因子2筛去)
- 然后发现 i % prime[j]==0,因为8=2*4,如果此时不跳出循环,下一步应筛去8*prime[j+1] = 8 * 3 = 24
- 而24的最小质因子是2,再考察上一步,发现8 * prime[j+1] = 8 * 3=2 * 4 * 3 = 4 * 3 * 2=12 * prime[j],也就是说如果此时将24筛去,当i增加至12时,24将被2再次筛选,
- 我们可以总结如下:当i%prime[j]==0时,有 i = prime[j] * k ,即 prime[j] * k *prime[j+1] 应当在在 i = k *prime[j+1] 时由prime[j]筛去,所以当发现当i%prime[j]==0时break,保证了每个合数只被它的最小的质因子筛选一次。