素数多写法

题目推荐:http://ybt.ssoier.cn:8088/problem_show.php?pid=1151

    https://www.luogu.com.cn/problem/P3383

第二个题数据规模有点儿doge,所以建议直接用欧拉筛来提交

第一种写法:朴素筛

1.O(n^2)写法

using namespace std;
//询问一个数,输出一行Yes或No。 
int n;
bool pd=1; 
int main()
{
       scanf("%d",&n);
       if(n==1)printf("No");//特判。
       for(int i=2;i<n;i++)//枚举到n前一个。
       {
        if(n%i==0)
        {
            pd=0;
            break;
        }
    }
    if(pd)printf("Yes");
    else printf("No");
    return 0;
    QWQ;
}

稍稍给它优化优化,枚举到√n;

2.O(n*√n)写法:

using namespace std;
//询问一个数,输出一行Yes或No。 
int n; 
bool pd=1; 
int main()
{
       scanf("%d",&n);
       if(n==1)printf("No");//特判。
       for(int i=2;i*i<=n;i++)//这次枚举到根号n,因为根号n到n之间的数都不是n的因数
       {
        if(n%i==0)
        {
            pd=0;
            break;
        }
    }
    if(pd)printf("Yes");
    else printf("No");
    return 0;
    QWQ;
}

但是这样按照此题要判断多次,时间复杂度肯定很高是不行滴 试过

接下来再介绍两种高效率区间筛:

 

二:埃氏筛

当需要求某一区间[2,n]内的所有素数时,可以从2开始,对于当前素数p,将p^2p2后所有p的倍数筛去每次找到下一个没有被筛到的数就是一个素数。

#include<bits/stdc++.h>
using namespace std;
int a[100005],n,q,x;
bool ss(int x)
{
    bool f=1;
    for(int i=2;i<=sqrt(x);i++)
    {
        if(x%i==0)
        {
            f=0;
            break;      
        }    
    }    
    return f;
} 
int main(){
    cin>>n>>q;
    int sum=1;
    for(int i=2;i<=n;i++){
        if(ss(i)){
            a[sum]=i;
            sum++;
        }
    }
    while(q--){
        cin>>x;
        cout<<a[x]<<endl;
    }
    return 0;
}

当然,这种算法并不完美,因为有些合数会被筛两次。

比如6,会被2筛一次,3一次,为了优化,我们用出了另一种更高效率的区间筛

所以:

三:欧拉筛

欧拉筛法的基本思想 :在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次,以达到不重复的目的。

具体详解,请见:https://blog.csdn.net/qq_39763472/article/details/82428602

#include<bits/stdc++.h>
using namespace std;
int sum=1,n,m,x,a[100000001];
bool un[100000001];

void oula(int x){
    for(int i=2;i<=n;i++){
        if(un[i]==false){
            a[sum++]=i;
        }
        for(int j=1;j<=sum && i*a[j]<=n;j++){
            un[i*a[j]]=true;
            if(i%a[j]==0) break;
        }
    }
} 

int main(){
    cin>>n>>m;
    oula(n);
    while(m--){
        cin>>x;
        cout<<a[x]<<endl;
    }
    return 0;
}

最后,奉上推荐题的AC代码,方便各位复制粘贴

1.

#include<iostream>
#include<cmath>
using namespace std;
bool judge(int x)
{
    bool f=1;
    for(int i=2;i<=sqrt(x);i++)
    {
        if(x%i==0)
        {
            f=0;
            break;      
        }    
    }    
    return f;
} 
int main()
{
    int n;
    int sum=0;
    cin>>n;
    for(int i=2;i<=n;i++)
    {
        if(judge(i))
        {
            sum++;
        }
    }
    cout<<sum<<endl;;
    return 0;
}

2.

#include<bits/stdc++.h>
using namespace std;
int sum=1,n,m,x,a[100000001];
bool un[100000001];

void oula(int x){
    for(int i=2;i<=n;i++){
        if(un[i]==false){
            a[sum++]=i;
        }
        for(int j=1;j<=sum && i*a[j]<=n;j++){
            un[i*a[j]]=true;
            if(i%a[j]==0) break;
        }
    }
} 

int main(){
    cin>>n>>m;
    oula(n);
    while(m--){
        cin>>x;
        cout<<a[x]<<endl;
    }
    return 0;
}

 

 

posted @ 2021-08-19 10:50  ssdaeda  阅读(52)  评论(1编辑  收藏  举报