求1e11以内的素数

  有两种做法,一种是打表,另一种是直接求。

 

打表

将1e11每隔len(len=2000w)个数字统计一下该区间内素数的个数,比如cnt[1] 表示[1,len]以内有多少个素数,cnt[2]表示[len+1,2*len】以内有多少个素数,依次类推。

然后维护一下前缀和,sum[i] = cnt[1] + ....+ cnt[i]

那么给定一个数字n,求[1,n]以内有多少个素数, 那么只要统计一下sum[n/len],然后再统计一下区间[n/len*len+1, n/len*len + n%len],由于这个内最多只有2000w个,那么只要对该区间内的数字进行筛法求素数,然后统计该区间内素数的个数就可以了。

任意区间内素数的个数

所以关键是如果求任意区间内素数的个数, 例如要求区间[a, b]内有多少个数字, 因为该区间内任意合数字的最大最小质因数不会超过sqrt(b),所以只要先求出区间[2,sqrt(b)]内的素数表,那么就可以用该素数表去筛去区间[a,b]内的所有合数。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long LL;
/*
 * 要求区间[a,b]以内的素数, 那么该区间内所有合数的最小质因数绝对不超过sqrt(b),
 * 所以只要求出[2,sqrt(b)]以内的所有素数,然后用这些素数筛去区间[a,b]内的所有合数即可
 * 要开的数组的大小
 * M > b - a
 * N > sqrt(b)
*/
const int N = 1000000;
const int M = 10000000;

bool is_prime[N];
int prime[N], cnt;
void get_prime(){
    for(int i=3; i<N; ++i)
        is_prime[i] = true;
    cnt = 0;
    prime[cnt++] = 2;
    for(LL i=3; i<N; i+=2){
        if(is_prime[i]){
            prime[cnt++] = i;
            for(LL j=i*i; j<N; j+=2*i){
                is_prime[j] = false;
            }
        }
    }
}

bool is_prime2[M];
int get_prime2(LL l, LL r){
    for(LL i=0; i<=r-l; ++i)
        is_prime2[i] = true;

    for(LL i=0; i<cnt && (LL)prime[i]*prime[i]<=r; ++i){
        /* (l+prime[i]-1)/prime[i]*prime[i] 得到最接近l的prime[i]的倍数是多少 */
        for(LL j=max(2LL, (l+prime[i]-1)/prime[i])*prime[i]; j<=r; j+=prime[i]){
            is_prime2[j-l] = false;
        }
    }
    int res = 0;
    //会把0和1当做素数,所以要减去
    if(l==0)
        res -= 2;
    if(l==1)
        res -= 1;
    for(LL i=0; i<=r-l; ++i){
        res += is_prime2[i];
        /* printf("%lld %d\n", i+l, is_prime2[i]); */
    }

    return res;
}
int main()
{
    /* freopen("in.txt","r",stdin); */
    /* freopen("out.txt","w",stdout); */
    get_prime();
    cout << get_prime2(1, 10000000) << endl;
    return 0;
}

 

转载于:https://www.cnblogs.com/justPassBy/p/5884828.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值