Eratosthenes筛法

    xiaoxiao2021-04-11  37

    如果要将素数建个表,我们可以从1~n每个数进行素数判断,如果是则放入数组里。这个效率不算很高,那么有一种算法可以更好实现——Eratosthenes筛法。它的思想就是:对于不超过n的每个非负整数p,删除2p,3p,4p,…,当处理完所有数之后,还没有被删除的就是素数。

    #include<cstdio> #include<cstring> using namespace std; const int maxn = 10000000; int vis[maxn]; void Eratosthenes(int n) { for(int i=2; i<=n; i++) { for(int j=2*i; j<=n; j+=i) { vis[j] = 1; } } return; } int main() { memset(vis,0,sizeof(vis)); int n; scanf("%d",&n); Eratosthenes(n); for(int i=2; i<=n; i++) { if(!vis[i]) { printf("%d ",i); } } return 0; }

    优化一下:在“对于不超过n的每个非负整数p”中,p可以限定为素数——只需在第二重循环前加一个判断if(!vis[i])即可,另外,内层循环不需从i*2开始,因为它已经在i=2时被筛掉了。

    #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int maxn = 10000000; int vis[maxn]; typedef long long L; void Eratosthenes(L n) { memset(vis,0,sizeof(vis)); L m = sqrt(n + 0.5); for(L i=2; i<=m; i++) { if(!vis[i]) { for(L j=i*i; j<=n; j+=i) { vis[j] = 1; } } } return; } int main() { L n; scanf("%lld",&n); Eratosthenes(n); for(L i=2; i<=n; i++) { if(!vis[i]) { printf("%lld ",i); } } return 0; }

    那么紫书上引出的问题: 无平方因子的数: 给出正整数n和m,区间[n,m]内的“无平方因子”的数有多少个? 正整数p无平方因子,当且仅当不存在k > 1,使得p是k^2的倍数。

    这个问题可以从n开始到m结束,然后一个个数去判断,这样明显爆炸。所以要采用筛素数的方式,从2到√m的素数p中,筛去区间[n.m]内p^2的所有倍数。

    代码如下:

    #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long LL; const LL maxn = 1000000000000; int vis[maxn], ans[maxn]; LL n, m; int main() { int n,m; memset(vis,0,sizeof(vis)); int t=sqrt(maxn+0.5); for(int i=2;i<=t;i++) if(!vis[i]) for(int j=i*i; j<=maxn; j+=i) vis[j]=1; //先筛素数 while(scanf("%d%d",&n,&m) == 2 && n && m) { int k = floor(sqrt(m+0.5)); memset(ans, 0, sizeof(ans)); for(int i=2; i<=k; i++) if(!vis[i]) { int last = m / (i*i); for(int crt=n/(i*i); crt<=last; crt++) ans[(i*i)*crt]=1; }//筛无平方因子数 int count=0; for(int i=n; i<=m; i++) { if(!ans[i]) { printf("%d ",i); count++; } } printf("\n"); printf("%d\n",count); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-666643.html

    最新回复(0)