欧拉线性筛法求素数 学习报告
2016-11-10 09:06
246 查看
筛素数的方法有很多,先说一下Eratosthenes筛法,这种筛法的思想不难理解,就是对不超过n的每个正整数p,依次删除p,2∗p,3∗p……(k−1)∗p,k∗p(k∗p<=n),最后没被筛除的就是素数了
代码也是很好写的,如下:
这个筛法效率还是很高的,内层的循环次数是x=⌊ni⌋−1<ni,这样,循环的总次数小于
n2+n3+n4+……+nn=O(nlogn)
所以这个筛法已经足够应付大多数题了.
但是如果n是107呢,在Eratosthenes筛法里,我们一个合数标记过很多遍,导致了时间的浪费,所以便有了一种时间复杂度近似O(n)的算法,就是欧拉线性筛法。这种筛法出去了很多冗余的标记和计算,先看下代码
根据唯一分解定理,我们可以得知任意一个合数N(N>2),都可以唯一分解成p1∗p2∗p3∗p4∗…∗pn, 其中p1≤p2≤p3≤p4≤…≤pn 且都是素数.
我们要确定的就是每个合数都要被筛除且只筛一遍
设合数n=p1∗p2∗p3∗…∗pn(p1≤p2≤p3≤…≤pn)
1.因为i是从1到N循环的,所以肯定先访问n′=p2∗p3∗p4∗…∗pn, 又因为p1≤p2,所以在访问n′的时候p1∗n′是一定执行的,由此我们可以得出所有的合数都会被标记过.
2.只要当前的i% prime[j]=0 就会退出循环,prime[j] 也是从小到大循环的,所以合数n只会在i=n′=p2∗p3∗p4∗…∗pn 的时候被筛掉,在i>n′ 时,有可能满足条件的i′=p1∗p2∗…∗pnpk(2≤k≤n),此时prime[k]∗i′ 可以把n筛除,而根据②,在prime[1] 就break跳出循环了,故一个合数n都会被筛除且只筛一遍.
总结:
还是要多做一些数论题,尤其这种基础算法一定要知道原理及证明,否则有变式的时候就不知所措了.
代码也是很好写的,如下:
#include<iostream> #include<cstdio> #define N 100000 using namespace std; int i,j; bool pd ; int main() { pd[1]=1; for(i=2;i<=N;i++) if(!pd[i]) for(j=i*i;j<=N;j+=i)//此处写成i*i,一个小优化 pd[j]=1; for(i=1;i<=N;i++) if(!pd[i]) printf("%d ",i); return 0; }
这个筛法效率还是很高的,内层的循环次数是x=⌊ni⌋−1<ni,这样,循环的总次数小于
n2+n3+n4+……+nn=O(nlogn)
所以这个筛法已经足够应付大多数题了.
但是如果n是107呢,在Eratosthenes筛法里,我们一个合数标记过很多遍,导致了时间的浪费,所以便有了一种时间复杂度近似O(n)的算法,就是欧拉线性筛法。这种筛法出去了很多冗余的标记和计算,先看下代码
#include<iostream> #include<cstdio> # define N 10000000 using namespace std; int num=0,i,j,prime[1000005]; bool pd[10000005]; int main() { for(i=2;i<=N;i++) { if(!pd[i]) prime[++num]=i;//①如果是素数,选取加入prime[] for(j=1;j<=num&&prime[j]*i<=N;j++) { pd[prime[j]*i]=1; if(!i%prime[j]) //②这是为了防止出现一个合数被判断两次的情况发生 break; } } for(i=1;i<=num;i++) printf("%d ",prime[i]); }
根据唯一分解定理,我们可以得知任意一个合数N(N>2),都可以唯一分解成p1∗p2∗p3∗p4∗…∗pn, 其中p1≤p2≤p3≤p4≤…≤pn 且都是素数.
我们要确定的就是每个合数都要被筛除且只筛一遍
设合数n=p1∗p2∗p3∗…∗pn(p1≤p2≤p3≤…≤pn)
1.因为i是从1到N循环的,所以肯定先访问n′=p2∗p3∗p4∗…∗pn, 又因为p1≤p2,所以在访问n′的时候p1∗n′是一定执行的,由此我们可以得出所有的合数都会被标记过.
2.只要当前的i% prime[j]=0 就会退出循环,prime[j] 也是从小到大循环的,所以合数n只会在i=n′=p2∗p3∗p4∗…∗pn 的时候被筛掉,在i>n′ 时,有可能满足条件的i′=p1∗p2∗…∗pnpk(2≤k≤n),此时prime[k]∗i′ 可以把n筛除,而根据②,在prime[1] 就break跳出循环了,故一个合数n都会被筛除且只筛一遍.
总结:
还是要多做一些数论题,尤其这种基础算法一定要知道原理及证明,否则有变式的时候就不知所措了.
相关文章推荐
- 线性筛素数的欧拉筛法
- (Relax 数论1.11)POJ 1595 Prime Cuts(欧拉筛法: 输出1~n区间中中间的2C个素数)
- 素数筛总结篇___Eratosthenes筛法和欧拉筛法(*【模板】使用 )
- [SDOI2008]沙拉公主的困惑 线性筛 素数+欧拉
- 线性求区间欧拉函数(顺便线性求区间内所有素数)(类似欧拉线性素数筛)
- 筛素数-欧拉筛法模板
- [转]线性筛法求质数(素数)表及其原理
- UVA11426 FZU1969 51NOD1188 线性欧拉筛法+筛法
- 【数论】(贾志鹏)线性欧拉筛模板&&CODE[VS] 1453 统计素数个数2
- 2016 UESTC Training for Math F - 粗心的谭爷 素数线性筛法的推广
- 线性筛(欧拉筛法)简介(洛谷P3383)
- (Relax 数论1.13)POJ 2909 Goldbach's Conjecture(欧拉筛法的应用:给出一个偶数,要求在这个偶数的范围内,有几对素数和是等于这个偶数的,注意素数对的不重复性! )
- 线性筛法(欧拉筛法)
- 线性筛法(欧拉筛法)求素数
- 线性筛法(欧拉筛法)求素数
- 使用欧拉筛法求素数和
- (大素数2.1.2.1)UVA 10871 Primed Subsequence(欧拉筛法)
- 数学_线性筛法建立素数表(HDU_1262)
- 求素数: 一般线性筛法 + 快速线性筛法
- 埃拉托斯特尼筛法 VS 欧拉筛法 (素数筛选) Java