zoukankan      html  css  js  c++  java
  • LightOJ1197【数学】

    引自:WONTER

    题意:

    给你两个数,a,b,让你求区间[a,b]里面有多少个素数;

    思路:

    首先要知道,我们要想筛 [1, b] 中所有的素数,只需要用到 [1, sqrt(b)] 中的所有素数来筛就可以了。

    假设我们是求 [1, b] 中所有的素数,我们就只需要打表出 [1, sqrt(b)] 的素数,然后用这些素数直接去套用常规的素数筛选方法就好了,也就是(j = prime[i] * 2; j <= b; j += prime[i]) isPrime[j] = false,但由于 b < 2^31 数据太大,我们不能直接开这么大的空间,就算能开,一个一个的置 false 也会 TLE

    由于 a 和 b 的范围太大,直接素数筛肯定不可以的,但注意到 b - a <= 100000,所以可以利用这一点,减少空间的使用。所以 j 就从第一个大于 a 的 prime[i] 的倍数开始,其他的不变,并且我们置为 false 的时候也不是置isPrime[j] = false,因为这个 j 会很大,我们把 j 离散化,置isPrime[j - a] = false即可,最后统计 [0, b - a] 中有多少个 isPrime[j]是 true 就可以了

    但要特判 a 为 1 的时候,1 也被算成素数了,这个时候要减去。

    这里有一个小小的CASE就是:

    求>=a的最小b倍;

    ①:大哥的写法:(a+b-1)/b*b;没有严格证明。。

    ②:队友写法:a+b-a%b,但还要判断是不是a%b!=0;

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
     
    const int N=1e5+10;
    bool isprime[N];
    vector<int>prime;
     
    void init()
    {
        prime.clear();
        for(int i=1;i<=55000;i++)
        {
            if(i&1)
                isprime[i]=true;
            else isprime[i]=false;
        }
        isprime[2]=1;
        for(int i=2;i<=55000;i++)
        {
            if(isprime[i])
            {
                prime.push_back(i);
                for(int j=i+i;j<=55000;j+=i)
                    isprime[j]=false;
            }
        }
    }
     
    int main()
    {
        init();
        int a,b;
        int T,cas=1;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&a,&b);
            memset(isprime,true,sizeof(isprime));
            for(int i=0;i<prime.size();i++)
            {
                if(1ll*prime[i]*prime[i]>b)
                    break;
                LL j;
                if(a/prime[i]<2)
                    j=prime[i]+prime[i];
                else
                    j=((1ll*a-1)/prime[i]+1)*prime[i];
                while(j<=b)
                {
                    isprime[j-a]=false;
                    j+=prime[i];
                }
            }
            int num=b-a;
            int ans=0;
            for(int i=0;i<=num;i++)
            {
                if(isprime[i])
                    ans++;
            }
            if(a==1)
                ans--;
            printf("Case %d: %d
    ",cas++,ans);
        }
        return 0;
    }








  • 相关阅读:
    ansible常用模块及参数(1)
    ansible搭建wordpress,安装nfs和rsync
    ElasticSearch 集群
    kibana数据操作
    ElasticSearch 交互使用
    Elasticsearch的基础安装
    Elasticsearch的简介
    redis数据审计
    redis数据迁移
    redis集群节点添加与删除
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6216821.html
Copyright © 2011-2022 走看看