51nod 1181 质数中的质数

题目描述

如果一个质数,在质数列表中的编号也是质数,那么就称之为质数中的质数。例如:3 5分别是排第2和第3的质数,所以他们是质数中的质数。现在给出一个数N,求>=N的最小的质数中的质数是多少(可以考虑用质数筛法来做)。
Input
输入一个数N(N <= 10^6)
Output
输出>=N的最小的质数中的质数。
Input示例
20
Output示例
31

这个题当时做的时候,觉得10^6=100000 然后一直wa,找不到wa点,交了两发后重看题目信息才改过来,一改数据范围就对了….惊了.

由题干信息得我们需要先知道有哪些数时质数,然后我们需要求出哪些在质数中的数他们的排列也是质数
所以首先需要一个数组存哪些数是质数,第二个表依次存入质数,第三个表存入第二个表的素数他的位置是不是素数,最后输出的时候如果vis2[i]>=n&&vis3[i]==0就可以输出这个结果(注意这里的等于号!!)
但是这里实际上不需要这么多数组,先贴代码,下面说

    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    #include<set>

    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int MAX_N=100000;

    int vis[1001010];
    int vis2[1001010];
    int vis3[1001010];
    int main()
    {
        ios::sync_with_stdio(false);
        memset(vis,0,sizeof(vis));
        memset(vis2,0,sizeof(vis2));
        memset(vis3,0,sizeof(vis3));
        vis[1]=1;
        ll qq=1;
        for(ll i=2;i<1001010;i++){
            if(!vis[i])
                for(ll j=i*2;j<=1001010;j=j+i)
                    vis[j]=1;
            if(vis[i]==0)
                vis2[qq++]=i;   
        }
        for(ll i=2;i<qq;i++){
            for(int w=i*2;w<=qq;w=w+i)
                vis3[w]=1;
        }
        int n;
        vis3[1]=1;
        while(cin>>n){
            int flag=0;
            for(int i=1;i<=qq&&flag==0;i++)
                if(vis2[i]>=n&&vis3[i]==0){
                    flag=1;
                    cout<<vis2[i]<<endl;
                }
        }
        return 0;
    }

这个代码用时46ms 内存占用13.6m

那么该怎么优化呢,首先vis数组起到的是标记一个数是不是素数,所以完全可以换成占用更小内存的bool类型
其次vis3数组的存在真的有必要吗,他仅仅就是查询这个数的位置是不是素数,完全可以用vis这个表来代替,可以删去,而且1000000的多次初始化 可能还会导致时间增加

优化代码如下:

#include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    #include<set>

    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int MAX_N=100000;

    bool vis[1001010];
    int vis2[1001010];
    int n;
    int main()
    {
        ios::sync_with_stdio(false);
        memset(vis,0,sizeof(vis));
        memset(vis2,0,sizeof(vis2));
        vis[1]=1;
        ll qq=1;
        for(ll i=2;i<1001010;i++){
            if(!vis[i])
                for(ll j=i*2;j<=1001010;j=j+i)
                    vis[j]=1;
            if(vis[i]==0)
                vis2[qq++]=i;   
        }
        while(cin>>n){
            int flag=0;
            for(int i=1;i<=qq&&flag==0;i++)
                if(vis2[i]>=n&&vis[i]==0){
                    flag=1;
                    cout<<vis2[i]<<endl;
                }
        }
        return 0;
    }

这份代码的时间为31ms,占用内存降到了6.7m,如果还是想优化的话,可能就需要牺牲时间来减小内存了,比如不打素数表,依次判断这个数是不是素数,如果是就存入vis2数组,然后可以自己测试一下1000000内有几个素数,然后对数组大小进行优化,同级里有一位小兄弟采用了这种方法,内存占用降到了2m,但是时间耗时为472ms,所以可以说是得不偿失,这里就不再贴代码了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值