Meisell-Lehmer算法(求1...n范围内的素数个数)

1000亿以内的素数统计(Meisell-Lehmer算法) 今年沈阳有个素数计数的题,但是数据到了1e11,大概用Meisell-Lehmer能跑到2、3秒的样子,但是据说还有一种Deleglise Rivat的算法特别快,大概1e16差不多才3、4秒的样子,但是网上没有找到板子,所以就发一个Meisell-Lehmer的模板,1e11内的数差不多都能在5秒内处理完:#include using namespace std; typedef long 阅读详情

求1...n范围内的素数个数有多少了,如果数据不大的话素筛肯定就可以了,但像HDU-5901中n的范围为10^11肯定就不能素筛了,所以这里介绍Meisell-Lehmer算法,代码颇是复杂,摘的网上的模板然后改成自己的代码习惯。


//Meisell-Lehmer算法

#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
const int N = 5e6 + 5;
const int M = 7;
const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;
int np[N];
int prime[N], pi[N];
int phi[PM+1][M+1], sz[M+1];
int getprime()
{
    int cnt = 0;
    np[0] = np[1] = 1;
    pi[0] = pi[1] = 0;
    for(int i = 2; i < N; ++i)
    {
        if(!np[i]) prime[++cnt] = i;
        pi[i] = cnt;
        for(int j = 1; j <= cnt && i * prime[j] < N; ++j)
        {
            np[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
    return cnt;
}
void init()
{
    getprime();
    sz[0] = 1;
    for(int i = 0; i <= PM; ++i) phi[i][0] = i;
    for(int i = 1; i <= M; ++i)
    {
        sz[i] = prime[i] * sz[i-1];
        for(int j = 1; j <= PM; ++j) phi[j][i] = phi[j][i-1] - phi[j/prime[i]][i-1];
    }
}
int sqrt2(LL x)
{
    LL r = (LL)sqrt(x - 0.1);
    while(r*r <= x) ++r;
    return (int)(r-1);
}
int sqrt3(LL x)
{
    LL r = (LL)cbrt(x - 0.1);	//cbrt(x): x的立方根
    while(r*r*r <= x) ++r;
    return (int)(r-1);
}
LL getphi(LL x, int s)
{
    if(s == 0) return x;
    if(s <= M) return phi[x%sz[s]][s] + (x/sz[s]) * phi[sz[s]][s];
    if(x <= prime[s]*prime[s]) return pi[x] - s + 1;
    if(x <= prime[s]*prime[s]*prime[s] && x < N)
    {
        int s2x = pi[sqrt2(x)];
        LL ans = pi[x] - (s2x+s-2)*(s2x-s+1)/2;
        for(int i = s+1; i <= s2x; ++i) ans += pi[x/prime[i]];
        return ans;
    }
    return getphi(x, s-1) - getphi(x/prime[s], s-1);
}
LL getpi(LL x)
{
    if(x < N) return pi[x];
    LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
    for(int i = pi[sqrt3(x)]+1, ed = pi[sqrt2(x)]; i <= ed; ++i) ans -= getpi(x/prime[i]) - i + 1;
    return ans;
}
LL lehmer_pi(LL x)
{
    if(x < N) return pi[x];
    int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
    int b = (int)lehmer_pi(sqrt2(x));
    int c = (int)lehmer_pi(sqrt3(x));
    LL sum = getphi(x, a) + (LL)(b+a-2) * (b-a+1)/2;
    for (int i = a+1; i <= b; ++i)
    {
        LL w = x/prime[i];
        sum -= lehmer_pi(w);
        if(i > c) continue;
        LL lim = lehmer_pi(sqrt2(w));
        for(int j = i; j <= lim; ++j) sum -= lehmer_pi(w/prime[j]) - (j-1);
    }
    return sum;
}
int main()
{
    LL n; init();
    while(~scanf("%lld",&n))
    {
        printf("%lld\n", lehmer_pi(n));
    }
    return 0;
}

还有一种简单的,但似乎慢一些.

#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
const LL maxn = 1e11;
const LL maxp = sqrt(maxn)+10;
LL f[maxp], g[maxp];
LL solve(LL n)
{
    LL i, j, m;
    for(m = 1; m*m <= n; ++m)
    f[m] = n/m-1;
    for(i = 1; i <= m; ++i) g[i] = i-1;
    for(i = 2; i <= m; ++i)
    {
        if(g[i] == g[i-1]) continue;
        for(j = 1; j <= min(m-1, n/i/i); ++j)
        {
            if(i*j < m)
            f[j] -= f[i*j] - g[i-1];
            else
            f[j] -= g[n/i/j] - g[i-1];
        }
        for(j = m; j >= i*i; --j) g[j] -= g[j/i] - g[i-1];
    }
    return f[1];
}
int main()
{
    LL n;
    while(scanf("%lld", &n) != EOF)
    {
    	printf("%lld\n", solve(n));
    }
    return 0;
}


还有一个方法来自一个官方题解

#include <cstdio>
#include <cmath>

#define MAXN 100  
#define MAXM 10001  
#define MAXP 40000  
#define MAX 400000 
#define LL long long
#define chkbit(ar, i) (((ar[(i) >> 6]) & (1 << (((i) >> 1) & 31))))  
#define setbit(ar, i) (((ar[(i) >> 6]) |= (1 << (((i) >> 1) & 31))))  
#define isprime(x) (( (x) && ((x)&1) && (!chkbit(ar, (x)))) || ((x) == 2))   
using namespace std; 

namespace pcf{  
    LL dp[MAXN][MAXM];  
    unsigned int ar[(MAX >> 6) + 5] = {0};  
    int len = 0, primes[MAXP], counter[MAX];  
    void Sieve()
    {  
        setbit(ar, 0), setbit(ar, 1);  
        for(int i = 3; (i*i) < MAX; i++, i++)
        {  
            if(!chkbit(ar, i))
            {  
                int k = i << 1;  
                for(int j = (i*i); j < MAX; j += k) setbit(ar, j);  
            }  
        }
        for (int i = 1; i < MAX; i++)
        {  
            counter[i] = counter[i-1];  
            if(isprime(i)) primes[len++] = i, counter[i]++;  
        }  
    }  
   
    void init()
    {  
        Sieve();  
        for(int n = 0; n < MAXN; n++)
        {  
            for(int m = 0; m < MAXM; m++)
            {  
                if(!n) dp[n][m] = m;  
                else dp[n][m] = dp[n-1][m] - dp[n-1][m/primes[n-1]];  
            }  
        }  
    }  
   
    LL phi(LL m, int n)
    {  
        if (n == 0) return m;  
        if (primes[n-1] >= m) return 1;  
        if (m < MAXM && n < MAXN) return dp[n][m];  
        return phi(m, n-1) - phi(m/primes[n-1], n-1);  
    }  
   
    LL Lehmer(LL m)
    {  
        if (m < MAX) return counter[m];  
        LL w, res = 0;  
        int i, a, s, c, x, y;  
        s = sqrt(0.9 + m), y = c = cbrt(0.9 + m);  
        a = counter[y], res = phi(m, a) + a - 1;  
        for (i = a; primes[i] <= s; i++) res = res - Lehmer(m/primes[i]) + Lehmer(primes[i]) - 1;  
        return res;  
    }  
}  
   
LL solve(LL n)
{  
    int i, j, k, l;  
    LL x, y, res = 0;  
    for (i = 0; i < pcf::len; i++)
    {  
        x = pcf::primes[i], y = n/x;  
        if ((x*x) > n) break;  
        res += (pcf::Lehmer(y) - pcf::Lehmer(x));  
    }  
    for (i = 0; i < pcf::len; i++)
    {  
        x = pcf::primes[i];  
        if ((x*x*x) > n) break;  
        res++;  
    }
    return res;  
}

int main()  
{  
    LL n;
    pcf::init();
    while(~scanf("%lld", &n))  
    {
        printf("%lld\n", pcf::Lehmer(n));  
    }  
    return 0;  
}

继续加油~~~

meissel-lehmer:梅塞尔莱默筛 梅塞尔莱默筛 这个长期停止的项目试图将 Meissel-Lehmer 筛法改进为可以快速计算出大的 pi(x) 值。 我记得 10^20 是我得到的最高值。 我认为这里最有趣的是原型文件夹中的程序 ML.c。 它将所有数据保存在内存中,因此不能超过 10^14,但我认为阅读此代码可以很好地理解算法的工作原理。 如 Lagarias、Miller 和 Odlyzko,计算 π(x):Meissel-Lehmer 方法中所述,通过 Meissel 方法计算 pi(x) 的实现。 所有程序都假定是 64 位机器,并且预计会在 32 位目标上失败。 它们已经在 Ubuntu 和 Redhat 下成功编译和运行。 立即下载

相关推荐

MobaXterm远程连接频繁掉线?3个SSH保活设置让你告别断连烦恼

本文针对MobaXterm远程连接频繁掉线问题,提供了3个SSH保活设置方案。从基础的SSH心跳机制到进阶的会话超时调整,再到TCP层保活与代理优化,全方位解决断连烦恼。特别适合需要稳定远程连接的开发者和运维人员,有效提升工作效率。

weixin_29250573的博客 486

Meissel-Lehmer 算法

由于 n 区间内的整数个数为 n,而对于任意一个块大小,块的数量为 n/n^{2/3}=n^{1/3},因此需要约为 n^{1/3} 个块才能覆盖这个区间内的所有数。3. 遍历 p 中的每个质数 p_i,从 p_i^2 开始,对于每个块 j,计算 g_{i,j} 表示 [1, n^{2/3}] 范围内 p_i 的倍数在第 j 块中出现的次数,使用前缀和的方法加速计算。其中 s_{i,j} 表示第 j 块内第 i 个质数,g_i,j 表示第 j 块内 [1, n^{2/3}] 范围内 p_i 的倍数的个数。

m0_72572901的博客 1059

【自动驾驶控制算法】 第一讲 绪论

声明【自动驾驶控制算法】系列是博主对所分享教学内容的学习笔记,并且该系列每篇博客都会将博主听课后总结的纸质版笔记附于文末,供大家参考。是一位研究汽车领域,无人驾驶方向及其相关方向的大佬,也算是博主在无人驾驶方向的启蒙老师。所以研究相关领域的朋友推荐去听一听他的视频讲解。...

iamtbon_1的博客 1796

【算法学习笔记】Meissel-Lehmer 算法 (亚线性时间找出素数个数)

「Meissel-Lehmer 算法」是一种能在亚线性时间复杂度内求出 \(1\sim n\) 内质数个数的一种算法。 在看素数相关论文时发现了这个算法,论文链接:Here。 算法的细节来自 OI wiki,转载仅作为学习使用。 目前先 mark 一下这个算法,等有空的时候再来研究一下,算法的时间复杂度为 \(\mathcal{O}(n^{\frac23})\) ,所以 \(n\) 的范围可以...

橘嘉禾 561

在Jetson orin NX上安装部署Yolov8

1、环境准备与依赖安装2、安装PyTorch和Torchvision:从NVIDIA官方论坛或开发者下载中心获取与你的JetPack版本兼容的PyTorch wheel文件。例如,对于JetPack 5.1.2,可以安装PyTorch v2.1.0 8。:需要编译安装与PyTorch版本匹配的Torchvision。这里自己编译没有成功,下载了一个现成的可以用torchvision-0.16.2+c6f3977-cp38-cp38-linux_aarch64.whl。

xxxcccvvvbbb的博客 776

WSL2迁移后用户名不见了?一招教你快速恢复Ubuntu22.04默认用户

本文针对WSL2迁移后Ubuntu 22.04默认用户名丢失的常见问题,提供了详细的诊断与修复方案。通过分析迁移底层逻辑,指导用户使用`ubuntu2204.exe config --default-user`命令或配置`/etc/wsl.conf`文件快速恢复用户身份,并涵盖权限修复、冲突解决及自动化迁移脚本等进阶内容,确保子系统迁移后环境完整可用。

web39explorer的博客 558

【C】Lehmer‘s GCD algorithm

【代码】【C】Lehmer's GCD algorithm。

amber_o0k的博客 333

STM32F103RC学习(一)

STM32F103RC学习(一)

Cat_South_North的博客 6057

Meisell-Lehmer算法(大素数模板)

比赛的时候搜到了这个模板,居然没细看……看到其他博主有说还有更快的叫Deleglise Rivat的算法,并没有搜到…… 网上搜的模板: #include #include #include #include #include #define LL long long using namespace std; const int N=5e6+2; bool np[N]; int p

Mandsnow 0w0 2106

io_uring vs epoll ,谁在网络编程领域更胜一筹?

简介:从定量分析的角度,通过量化 io_uring 和 epoll 两种编程框架下的相关操作的耗时,来分析二者的性能差异。 本文作者:王小光,「高性能存储技术SIG」核心成员。 背景 io_uring 在传统存储 io 场景已经证明其价值,但 io_uring 不仅支持传统存储 io,也支持网络 io。io_uring 社区有众多的开发者尝试将 io_uring 用于网络应用。我们之前也在《你认为 io_uring 只适用于存储 IO?大错特错!》中也探索过 io_uring 在网络场景的应用及其

阿里云云栖号 3035

社区版 ABAP MCP 能不能读取 SAP S/4HANA 公有云开发对象,我的判断是能试,但不能当成已被 SAP 背书的标准通道

文章摘要:当前存在多个社区项目(如mcp-abap-adt、mcp-abap-abap-adt-api等)通过包装ABAP ADT能力为MCP Server,使AI开发工具能读取ABAP对象。这些项目技术上依赖ADT HTTP API或SAP官方ADT language server,但针对SAP S/4HANA Cloud Public Edition的完整适配仍存在挑战。SAP官方已通过VS Code扩展提供ADT MCP能力,而社区方案在云环境下需遵循ABAP Cloud的严格限制,仅能访问已授权的开

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 87

素数问题——Meisell-Lehmer算法

素数问题——Meisell-Lehmer算法

OPM的博客 3047

Dify基础:Dify平台的本地化部署(含windows部署中,常见问题及解决方案)

第一种比较简单,只需要在浏览器中,打入https://dify.ai/就可以。这个指令虽然看起来简单,但实际上涉及到对docker的使用。这个项目既然有github地址,那它一般就是开源的。我们点开这个github地址,便能看到dify的私有化部署方式。我们可以看到,还是上面那个图,有个按钮,是指向该项目的Github地址的。第二步:按照dify的github给出的指令,对dify进行安装。第一步:我们把dify下载到自己的电脑(或者服务器)上。这里,我们只考虑第二种方式,也就是私有化部署。

xiezhipu的博客 1万+

hdu 5901 Count primes +Meisell-Lehmer算法

Count primes Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 3211 Accepted Submission(s): 1628 [submit] [discuss] Problem Description Easy question! Calculate how many primes between

m0_48008495的博客 233

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

HDU 5901 Count primes( Meisell-Lehmer算法模板 )

链接:传送门 题意:计算 [ 1 , n ] 之间素数的个数,(1 <= n <= 1e11) 思路:Meisell-Lehmer算法是计算超大范围内素数个数的一种算法,原理并不明白,由于英语太渣看不懂WIKI上的原理,附WIKI链接:Here /***************************************************************...

dijingzhou4259的博客 224

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

求1~n中素数个数的几种方法C/C++

第一种:典型暴力求法,但时间复杂度较高,效率较低 #include<bits/stdc++.h> using namespace std; int main() { int n,f; cin >> n; int cnt = 0; for (int i = 2; i <= n; i++) { f=1; for(int j = 2; j <=sqrt(i); j++) { if(i%j==0){ f=0; bre

深巷 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Meisell-Lehmer大素数计数 求第i个素数 + 二分

数据到1e11,用Meisell-Lehmer能跑到2、3秒,但是据说还有一种Deleglise Rivat的算法特别快,大概1e16差不多才3、4秒的样子,但是网上没有找到板子,所以就发一个Meisell-Lehmer的模板,1e11内的数差不多都能在5秒内处理完: #include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 5e6 + 2; bool np[N]; int pri

。 370

求n很大时求,<= n的素数的个数(时间复杂度o(n ^ 2 / 3)模板

//Meisell-Lehmer #include #include using namespace std; #define LL long long const int N = 5e6 + 2; bool np[N]; int prime[N], pi[N]; int getprime() { int cnt = 0; np[0] = np[1] = true; pi[

AI_xue 1353

hdu5901 Meisell-Lehmer算法求素数个数

题目大意:让你求1-n里面有几个素数(1&lt;=n&amp;&amp;n&lt;=1e11)。 算法思路:这里的n非常大,因此我们用Meisell-Lehmer算法求1-n的个数,该算法的复杂度为n^(2/3) #include&lt;cstdio&gt; #include&lt;cmath&gt; using namespace std; #define LL long long ...

huyifan1的博客 298

hdu5901 Count primes(求[1,1e11]的质数个数,亚线性Meisell-Lehmer算法,模板题)

题意: 给定n,计算[1,n]范围内的素数个数。 数据范围:n<=1e11 解法: 抄的别人的Meisell-Lehmer模板 code: #include <bits/stdc++.h> #define ll long long using namespace std; ll f[340000],g[340000],n; void init(){ ll i,j,m; for(m=1;m*m<=n;++m)f[m]=n/m-1; for(i=1;i<=

zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 206

Meissel-Lehmer算法(求N以内素数个数)

比欧拉筛快。 #define MAXN 100 // pre-calc max n for phi(m, n) #define MAXM 10010 // pre-calc max m for phi(m, n) #define MAXP 40000 // max primes counter #define MAX 400010 // max prime #define setbit(ar, i) (((ar[(i) >> 6]) |= (1 << (((i) >

Joker_He的博客 808

算法——素数问题全解

1.线性素数筛(试除法) 适用范围:判定数据不大,数据量级别较小(一般超过10000就要慎重了)。 一般来说,“素数判定” 对这道题目来说只是辅助的话,用这个方法就可以过的。 int Isprime(int x) { //素数定义为大于1的自然数,不用考虑出现0,1负数的情况 for (int i = 2; i <= sqrt(x); i++) { ...

weixin_30266885的博客 499

SCUT - 142 - 第n个素数

https://scut.online/p/142 但是洲阁筛打表还是超时了,打的表不够长吧,在51nod上面要跑5s。要是快10倍得要密1000倍,根本打不出来(时间意义)。 暴力check要找的质数是不是要的那个。 #include<bits/stdc++.h> typedef long long ll; using namespace std; const int M...

weixin_30664051的博客 113

HDU 5901 Count primes (Meisell-Lehmer算法 -- 模板)

题意: 给你一个数n ,求1~n 之间素数的个数(n (Meisell-Lehmer算法) 看的别人的博客: http://www.cnblogs.com/Kurokey/p/5888386.html 数组大小开到 sqrt n 就好了! #include #include using namespace std; #define LL long long co

aozil_yang的博客 669

HDU 5901 Count primes(Meisell-Lehmer算法)

Description 求111~nnn中有多少素数 Input 多组用例,每组用例输入一整数n(1≤n≤1011)n(1≤n≤1011)n(1\le n\le 10^{11}) Output 输出111~nnn中素数个数 Sample Input 2 3 10 Sample Output 1 2 4 Solution Meisell−LehmerMeisell−L...

ZSQ 591
上一篇: 关于数论乘法逆元及相关知识点
下一篇: HDU 5898 数位DP
薄层
博客等级 码龄10年 242粉丝 289原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值