Eratosthenes筛法
2017-04-13 13:45
501 查看
如果要将素数建个表,我们可以从1~n每个数进行素数判断,如果是则放入数组里。这个效率不算很高,那么有一种算法可以更好实现——Eratosthenes筛法。它的思想就是:对于不超过n的每个非负整数p,删除2p,3p,4p,…,当处理完所有数之后,还没有被删除的就是素数。
优化一下:在“对于不超过n的每个非负整数p”中,p可以限定为素数——只需在第二重循环前加一个判断if(!vis[i])即可,另外,内层循环不需从i*2开始,因为它已经在i=2时被筛掉了。
那么紫书上引出的问题:
[b]无平方因子的数: 给出正整数n和m,区间[n,m]内的“无平方因子”的数有多少个?
正整数p无平方因子,当且仅当不存在k > 1,使得p是k^2的倍数。
这个问题可以从n开始到m结束,然后一个个数去判断,这样明显爆炸。所以要采用筛素数的方式,从2到√m的素数p中,筛去区间[n.m]内p^2的所有倍数。
代码如下:
#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; }
那么紫书上引出的问题:
[b]无平方因子的数: 给出正整数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; }
相关文章推荐
- Eratosthenes筛法求素数
- Eratosthenes筛法--Haskell实现
- Eratosthenes筛法求1-100之间的素数
- 素数筛总结篇___Eratosthenes筛法和欧拉筛法(*【模板】使用 )
- Eratosthenes筛法
- 找质数算法(Sieve of Eratosthenes筛法)
- POJ 2262 Goldbach's Conjecture(Eratosthenes筛法)
- Eratosthenes筛法(素数筛)
- 数论初步——Eratosthenes筛法
- 用 Eratosthenes筛法构造1-n的素数表.
- 找质数算法(Sieve of Eratosthenes筛法)
- C++ 数论-Eratosthenes筛法
- Sieve of Eratosthenes(埃拉托斯尼斯筛法)
- Eratosthenes筛法和欧拉筛法对比
- Eratosthenes筛法生成素数表
- Eratosthenes筛法(埃氏筛法)
- Eratosthenes筛法
- 区间[A,B]与N互素的元素个数 [容斥][Eratosthenes筛法]
- Eratosthenes筛法的粗糙汇编源代码
- 用Eratosthenes筛法查找质数