jzxx1131 聪明的小地鼠(筛选法求素数)
2018-02-25 17:26
274 查看
jzxx1131 聪明的小地鼠(筛选法求素数)
时空限制 1000ms/16MB题目描述
在学校里的试验田里面,种了n个大萝卜,小地鼠又非常的喜欢吃萝卜。它呢,就会出来偷偷的从试验田中偷萝卜。大萝卜都是种在一排地里面,认真的管理员,按照萝卜的位置早早的给萝卜编了号。希望能增加管理,保证产量。谁知道,小地鼠也有了自己的偷萝卜策略。 同样,在这个地里呢,正好也有n只小地鼠,这些小地鼠,他们都是按照顺序出来偷萝卜。小地鼠们根据自己的出场顺序编好号,然后开始根据自己的编号开始偷萝卜。因为,小地鼠的老大(即1号老鼠),很胖,所以他决定多偷萝卜了,而只是拿了1号萝卜,把剩余的萝卜交给他的小弟们。当然,他为了让管理员还能够有点收入,好以后继续种萝卜,就给小弟们,下达了一个命令。即每个地鼠只能拿自己编号倍数的大萝卜,但是不能拿与自己编号相同的萝卜。这样就能稍微给管理员留下一些萝卜了。可怜的管理员,你能告诉他,他最后能够剩下的大萝卜编号。输入
有一个正整数n,代表大萝卜的个数(即地鼠的个数),(5 < n <= 1000)输出
有若干个,代表侥幸存活下来的萝卜的编号。由小到大输出且两个编号间用两个空格隔开。样例输入
10样例输出
2 3 5 7分析
此题简单解释为 1~n 的素数。解法就是埃拉托斯特尼筛法,也就是常说的 埃氏筛法 ,或者我们常说的 筛选法求素数。埃氏筛法
要得到自然数n以内的全部素数,必须把不大于的所有素数的倍数剔除,剩下的就是素数。
给出要筛数值的范围n,找出以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去......。步骤详细列出算法如下: 1、列出2以后的所有序列: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 2、标出序列中的第一个素数,也就是2,序列变成: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 3、将剩下序列中,划掉2的倍数,序列变成: 2 3 5 7 9 11 13 15 17 19 21 23 25 4、如果现在这个序列中最大数小于最后一个标出的素数的平方,那么剩下的序列中所有的数都是素数,否则回到第二步。 5、本例中,因为25大于2的平方,我们返回第二步: 6、剩下的序列中第一个素数是3,将主序列中3的倍数划掉,主序列变成:
2 3 5 7 11 13 17 19 23 25 7、我们得到的素数有:2,3 8、25仍然大于3的平方,所以我们还要返回第二步:
9、现在序列中第一个素数是5,同样将序列中5的倍数划掉,主序列成了: 2 3 5 7 11 13 17 19 23 10、我们得到的素数有:2,3,5 。 11、因为23小于5的平方,跳出循环. 结论:2到25之间的素数是:2 3 5 7 11 13 17 19 23 埃氏筛法:时间复杂度O(sqrt(N)log2(log2N)) 空间复杂度 O(N)
[b]埃氏筛法C++实现
[/b]
#include<iostream> #include<algorithm> #include<cmath> using namespace std; const int N = 100005; bool a ; int main(){ int n; cin>>n; fill(a,a+N,true); a[0]=a[1]=false; for (int i=2,t=sqrt(n); i<=t; i++) //埃氏筛选法求素数 if (a[i]) for (int j=i*i; j<=n; j+=i) a[j]=false; for (int i=2,k=0; i<=n; i++) if (a[i]){ if (++k==1) cout<<i; else cout<<" "<<i; } cout<<endl; return 0; }
改进型埃氏筛法
上述筛选法没有把素数存起来,我们在刷题时,很多要用到素数,怎么办?就把素数存起来呗。改进型埃氏筛法:[b]时间复杂度O(N-sqrt(N)+sqrt(N)log2(log2N)) 空间复杂度 O(N)[/b]
[b]改进型埃氏筛法C++实现[/b]#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 100005;
int a
;
int main(){
int n,i,j;
cin>>n;
fill(a,a+N,1);
a[0]=a[1]=0;
int t=sqrt(n);
for (i=2; i<=t; i++) //改进型埃氏筛法 复杂度:O(sqrt(N)*log(log(N)))
if (a[i]){
a[++a[0]]=i;
for (j=i*i; j<=n; j+=i) a[j]=0;
}
while (i<=n){ //O(N-sqrt(N))
if (a[i]) a[++a[0]]=i;
i++;
}
//总复杂度基本为O(n)
//经过此番计算 得到第i个质数为a[i] 而a[0]存储[1,n]内素数的个数
for (int i=1; i<a[0]; i++)
cout<<a[i]<<" ";
cout<<a[a[0]]<<endl;
return 0;
}
代码
#include<iostream> #include<algorithm> using namespace std; bool a[1005]; int main(){ int n; cin>>n; fill(a,a+1005,true); a[1]=false; for (int i=2; i<=n; i++) //埃氏筛选法求素数 if (a[i]) for (int j=i*i; j<=n; j+=i) a[j]=false; cout<<2; for (int i=3; i<=n; i++) if (a[i]) cout<<" "<<i; cout<<endl; return 0; }
相关文章推荐
- 黑马程序员————java实现:筛选法求素数
- 求出100以内的所有素数--筛选法和根号法
- HDU2303(数论)大整数求余+素数筛选
- poj 2689 (素数二次筛选)
- poj1595 Prime Cuts (素数筛选)
- 大区间素数筛选(POJ 2689)
- 大区间素数筛选(POJ 2689)
- 素数筛选,整数的唯一分解,整数所有因子之和,递归求等比数列前n项和
- 三种素数筛选方法
- 素数打表(三种筛选法)
- ACM常用素数判断筛选法及其优化
- Poj 2689 Prime Distance ----大区间素数筛选
- 素数筛选法--快速查找素数
- [转]筛选法求素数
- POJ2635The Embarrassed Cryptographer(大数取余+素数筛选+好题)
- 再讲素数筛选法
- 筛选法快速查找素数
- LightOJ 1197 Help Hanzo(区间素数筛选)
- 筛选生成素数
- hdu how many prime numbers 筛选法求素数