您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: