min25筛学习

Min25筛是一种在亚线性时间复杂度内求解一类积性函数前缀和的算法。它基于埃氏筛的思想,通过递推式计算,特别适用于完全积性函数。算法首先定义辅助函数g(n,i),表示筛掉前i个质数后剩余数的f值之和,并通过递推更新g值。然后,利用S函数表示最小质因子大于指定质数的数的f值之和。最后,通过S(n,0)+f(1)得到最终答案。该算法避免了计算非完全积性函数的g值,提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

min25筛能在在亚线性时间复杂度求出一类积性函数的前缀和,前提是这个积性函数在质数和质数的幂等位置的函数值比较好求。它借助埃氏筛的思想,将原问题转化为在质因子处的相似的子问题,从而得到一个递推式,达到快速求解的目的。


算法原理

一些符号

为了方便描述,定义以下符号:
设我们的问题是求 F ( n ) ∑ i = 1 n f ( i ) F(n)\sum\limits_{i=1}^nf(i) F(n)i=1nf(i),假设 f ( i ) f(i) f(i)是一个完全积性函数。

  • m i n p ( i ) minp(i) minp(i),表示 i i i的最小质因子
  • p r k pr_k prk,表示 n n n以内第 k k k个质数
  • ∣ p r ( n ) ∣ |pr(n)| pr(n),表示 n n n以内质数的个数

g函数

g ( n , i ) g(n,i) g(n,i)表示在埃氏筛中,在 n n n以内前 i i i个质数筛完后,剩下的数的 f f f值之和。剩下的数包含所有质数,以及最小质因子大于 p r i pr_i pri的合数。

g ( n , i ) = ∑ ( j ∈ p r i m e ) ∧ ( m i n p ( j ) > p r i ) f ( j ) g(n,i)=\sum\limits_{(j\in prime)\wedge(minp(j)>pr_i)}f(j) g(n,i)=(jprime)(minp(j)>pri)f(j)

由此可知 g ( n , ∣ p r ( n ) ∣ ) g(n,|pr(n)|) g(n,pr(n))表示做完埃氏筛后未被删掉的数(即 n n n以内所有质数)的 f f f值之和, g ( p r k , k ) g(pr_k,k) g(prk,k)表示前 k k k个质数的 f f f值之和。

我们可以用如下递推式求 g ( n , i ) g(n,i) g(n,i)

g ( n , i ) = { g ( n , i − 1 ) p r i 2 > n g ( n , i − 1 ) − f ( p r i ) × ( g ( ⌊ n p r i ⌋ , i − 1 ) − g ( p r i − 1 , i − 1 ) ) p r i 2 ≤ n g(n,i)= \begin{aligned} \left\{\begin{matrix} g(n,i-1)\qquad &pr_i^2>n \\ \\ g(n,i-1)-f(pr_i)\times(g(\lfloor\dfrac{n}{pr_i}\rfloor,i-1)-g(pr_{i-1},i-1)) \qquad &pr_i^2\leq n \end{matrix}\right. \end{aligned} g(n,i)= g(n,i1)g(n,i1)f(pri)×(g(⌊prin,i1)g(pri1,i1))pri2>npri2n

对于第一部分,因为 p r i 2 > n pr_i^2>n pri2>n,所以在埃氏筛中 p r i pr_i pri无法筛掉任何一个数,所以等于上一个状态。在埃氏筛中,一个合数只会被它的最小质因数筛掉,而质数不会被筛。

对于第二部分, g ( n , i ) g(n,i) g(n,i)所包含的 f f f值,等于 g ( n , i − 1 ) g(n,i-1) g(n,i1)所包含的 f f f值减去 p r i pr_i pri筛掉的数的 f f f值,即减去最小质因子为 p r i pr_i pri的合数的 f f f值。

我们发现这个式子也可以写成含 g g g的表达式,即 f ( p r i ) × ( g ( ⌊ n p r i ⌋ , i − 1 ) − g ( p r i − 1 , i − 1 ) ) f(pr_i)\times(g(\lfloor\dfrac{n}{pr_i}\rfloor,i-1)-g(pr_{i-1},i-1)) f(pri)×(g(⌊prin,i1)g(pri1,i1))。其中 g ( ⌊ n p r i ⌋ , i − 1 ) g(\lfloor\dfrac{n}{pr_i}\rfloor,i-1) g(⌊prin,i1) ⌊ n p r i ⌋ \lfloor\dfrac{n}{pr_i}\rfloor prin以内用前 i − 1 i-1 i1个质数筛过后的 f f f值之和,它包含两个部分:

  • 最小质因子大于 p r i − 1 pr_{i-1} pri1的数的 f f f
  • i − 1 i-1 i1个质数的 f f f值,即 g ( p r i − 1 , i − 1 ) g(pr_{i-1},i-1) g(pri1,i1)

那么减掉第二部分后,得到的是 ⌊ n p r i ⌋ \lfloor\dfrac{n}{pr_i}\rfloor prin以内最小质因子大于 p r i − 1 pr_{i-1} pri1的数的 f f f值。如果再乘上 p r i pr_i pri,得到的是 n n n以内最小质因子等于 p r i pr_i pri的合数的 f f f值之和,这部分就是 p r i pr_i pri筛去的数的 f f f值之和。

但是只有当 f f f为完全积性函数时, f ( p r i ) f(pr_i) f(pri)才能提取出来。而这里 f f f是积性函数,却不一定是完全积性函数,我们怎么能够这样推出式子呢?而且,这个递推式的初始条件是 g ( n , 0 ) g(n,0) g(n,0),而 g ( n , 0 ) g(n,0) g(n,0)正是题目要求的,怎么可以用来做初始值呢?

其实在这里的 g ( n , 0 ) g(n,0) g(n,0)所求的并不是真正的 f f f值之和,它求的是另一个完全积性函数的和,假设这个函数为 f ′ f' f。在质数位置和质数幂的位置, f ′ f' f值与 f f f值相等;而在其他位置, f ′ f' f值与 f f f值不一定相等。设置 f ′ f' f的目的,是因为这里需要完全积性函数。用 f ′ f' f代替 f f f,即可使递推式成立。

下文要求的 g g g值中只包含 f f f在质数和质数幂处的值,其他地方的值都被筛掉了,所以求出的答案是正确的。

递推式已经推出来了,接下来看看如何实现。

g g g函数有两个参数直接做的话,时间复杂度和空间复杂度都很大。我们发现第二维是可以滚动的,所以空间上可以省掉第二维。
s i = g ( p r i , i ) s_i=g(pr_i,i) si=g(pri,i),则 s i s_i si可以在求质数时求出。又因为 ⌊ ⌊ n a ⌋ b ⌋ = ⌊ n a b ⌋ \lfloor\dfrac{\lfloor\frac na\rfloor}{b}\rfloor=\lfloor\dfrac{n}{ab}\rfloor ban=abn,所以在递推中所有 g g g值的参数都在数论分块 2 n 2\sqrt n 2n 个值之中。所以我们一开始将这 2 n 2\sqrt n 2n 个数先存起来,然后在上面进行滚动求值。

code

void init(){
	x=sqrt(n)+1;
	dd();//埃氏筛
	for(long long l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		v[++vt]=n/l;//记下数论分块中可能用到的值
		if(n/l<=x) f[0][n/l]=vt;
		else f[1][l]=vt;
		long long t=n/l;
		g[vt]=...;//求g(v[vt],0)处的值
	}
	long long w;
	for(int i=1;i<=p1;i++){
		w=1ll*pr[i]*pr[i];
		long long t;
		for(int j=1;j<=vt&&w<=v[j];j++){
			t=v[j]/pr[i];
			if(t<=x) t=f[0][t];
			else t=f[1][n/t];
			g[j]=(...);//求g(j,i)的值
		}
	}//滚动求g(n,i)
}

S函数

S ( n , i ) S(n,i) S(n,i)表示 n n n以内的最小质因子大于 p r i pr_i pri的数的 f f f值之和,则有

S ( n , i ) = g ( n , ∣ p r ( n ) ∣ ) − g ( p r i , ∣ p r ( n ) ∣ ) + ∑ j > i ∑ p r j k ≤ n f ( p r j k ) × ( S ( ⌊ n p r j k ⌋ , j ) + [ k > 1 ] ) S(n,i)=g(n,|pr(n)|)-g(pr_i,|pr(n)|)+\sum\limits_{j>i}\sum\limits_{pr_j^k\leq n}f(pr_j^k)\times (S(\lfloor\dfrac{n}{pr_j^k}\rfloor,j)+[k>1]) S(n,i)=g(n,pr(n))g(pri,pr(n))+j>iprjknf(prjk)×(S(⌊prjkn,j)+[k>1])

其中 g ( n , ∣ p r ( n ) ∣ ) − g ( p r i , ∣ p r ( n ) ∣ ) g(n,|pr(n)|)-g(pr_i,|pr(n)|) g(n,pr(n))g(pri,pr(n))表示 n n n以内大于 p r i pr_i pri的质数的 f f f值之和。后面相当于求 n n n以内不是质数的最小质因子大于 p r i pr_i pri的数的 f f f值之和。当 k = 1 k=1 k=1时, f ( p r j ) f(pr_j) f(prj)在前面已经被计算过了,所以不用加1;当 k > 1 k>1 k>1时, p r j k pr_j^k prjk不是质数,所以要加上。

S S S的初始值为 S ( n , ∣ p r ( n ) ∣ ) = 0 S(n,|pr(n)|)=0 S(n,pr(n))=0

我们要求的是 S ( n , 0 ) + f ( 1 ) S(n,0)+f(1) S(n,0)+f(1)

观察上述的递推式,前两项已经求出。最后一项有两个求和号,分别枚举质因数和它的幂数。

p r j 2 > n pr_j^2>n prj2>n时,在 k = 1 k=1 k=1 S ( ⌊ n p r j k ⌋ , j ) S(\lfloor\dfrac{n}{pr_j^k}\rfloor,j) S(⌊prjkn,j)显然为 0 0 0 ⌊ n p r j k ⌋ < p r j \lfloor\dfrac{n}{pr_j^k}\rfloor<pr_j prjkn<prj,不可能有数在 ⌊ n p r j k ⌋ < p r j \lfloor\dfrac{n}{pr_j^k}\rfloor<pr_j prjkn<prj以内且最小质因子大于 p r j pr_j prj)。所以我们只要求 n \sqrt n n 以内的质因子。而 S ( ⌊ n p r j k ⌋ , j ) S(\lfloor\dfrac{n}{pr_j^k}\rfloor,j) S(⌊prjkn,j)中第一个参数也只能取数论分块的 2 n 2\sqrt n 2n 个值。

code

long long S(long long p,int q){
	if(pr[q]>=p) return 0;
	long long td=(p<=x?f[0][p]:f[1][n/p]);
	long long re=((g[td]-s[q])%mod+mod)%mod;//前两项
	for(int j=q+1;j<=p1;j++){
		if(1ll*pr[j]*pr[j]>p) break;
		for(long long o=1,pq=pr[j];pq<=p;++o,pq=pq*pr[j]){
			re=(re+1ll*(...)%mod*(S(p/pq,j)%mod+(o>1))%mod)%mod;//最后一项
		}
	}
	return re;
}

思考

观察 S ( n , i ) S(n,i) S(n,i)的递推式,将其改成如下式子

S ( n , i ) = ∑ j > i ∑ p r j k ≤ n f ( p r j k ) × ( S ( ⌊ n p r j k ⌋ , j ) + 1 ) S(n,i)=\sum\limits_{j>i}\sum\limits_{pr_j^k\leq n}f(pr_j^k)\times (S(\lfloor\dfrac{n}{pr_j^k}\rfloor,j)+1) S(n,i)=j>iprjknf(prjk)×(S(⌊prjkn,j)+1)

递推式意义不变,而且不用求 g g g函数了。那为什么我们不能用这个式子来求 S S S呢?

注意当 + [ k > 1 ] +[k>1] +[k>1]变为 + 1 +1 +1时,若 k = 1 k=1 k=1 p r j 2 > n pr_j^2>n prj2>n,则 p r j pr_j prj也有贡献,这就要求我们求出 n n n以内的所有质数。一般的 n n n都是 1 0 9 10^9 109以上的级别的,这显然是不可行的。


总结

min25筛的时间复杂度为 O ( n 3 4 ln ⁡ n ) O(\dfrac{n^{\frac 34}}{\ln n}) O(lnnn43),相对于杜教筛来说,min25筛要快一些,而且不用找 g , h g,h g,h以及求它们的前缀和。

有时候题目中的 f f f是一个多项式,我们需要把它拆开,对每一项都用 g g g的递推式求一次,最后再求和。


例题

洛谷P5325 【模板】Min_25筛

f ( p k ) = p k ( p k − 1 ) = p 2 k − p k f(p^k)=p^k(p^k-1)=p^{2k}-p^k f(pk)=pk(pk1)=p2kpk,令 f 1 ( x ) = x 2 f_1(x)=x^2 f1(x)=x2 f 2 ( x ) = x f_2(x)=x f2(x)=x,则 f ( p k ) = f 1 ( p k ) + f 2 ( p k ) f(p^k)=f_1(p^k)+f_2(p^k) f(pk)=f1(pk)+f2(pk)。因为 f 1 f_1 f1 f 2 f_2 f2都是完全积性函数,所以我们可以分别将 f 1 , f 2 f_1,f_2 f1,f2带入 g g g的递推式中,做min25筛。

code

#include<bits/stdc++.h>
using namespace std;
const int N=200000;
const long long mod=1000000007;
int p1,vt,z[N+5],pr[N+5];
long long n,x,ny,v[N+5],f[2][N+5],s1[N+5],s2[N+5],g1[N+5],g2[N+5];
long long mi(long long t,long long v){
	if(!v) return 1;
	long long re=mi(t,v/2);
	re=re*re%mod;
	if(v&1) re=re*t%mod;
	return re; 
}
void dd(){
	for(int i=2;i<=N;i++){
		if(!z[i]){
			pr[++p1]=i;
			s1[p1]=(s1[p1-1]+1ll*i*i%mod)%mod;
			s2[p1]=(s2[p1-1]+i)%mod;
		}
		for(int j=1;j<=p1&&i*pr[j]<=N;j++){
			z[i*pr[j]]=1;
			if(i%pr[j]==0) break;
		}
	}
}
void init(){
	x=sqrt(n)+1;
	ny=mi(6ll,mod-2);
	dd();
	for(long long l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		v[++vt]=n/l;
		if(n/l<=x) f[0][n/l]=vt;
		else f[1][l]=vt;
		long long t=(n/l)%mod;
		g1[vt]=(t*(t+1)%mod*(2*t+1)%mod*ny%mod-1+mod)%mod;
		g2[vt]=(t*(t+1)/2%mod-1+mod)%mod;
	}
	long long w;
	for(int i=1;i<=p1;i++){
		w=1ll*pr[i]*pr[i];
		long long t;
		for(int j=1;j<=vt&&w<=v[j];j++){
			t=v[j]/pr[i];
			if(t<=x) t=f[0][t];
			else t=f[1][n/t];
			g1[j]=(g1[j]-1ll*pr[i]*pr[i]%mod*(g1[t]-s1[i-1])%mod+mod)%mod;
			g2[j]=(g2[j]-1ll*pr[i]*(g2[t]-s2[i-1])%mod+mod)%mod;
		}
	}
}
long long S(long long p,int q){
	if(pr[q]>=p) return 0;
	long long td=(p<=x?f[0][p]:f[1][n/p]);
	long long re=((g1[td]-s1[q]-g2[td]+s2[q])%mod+mod)%mod;
	for(int j=q+1;j<=p1;j++){
		if(1ll*pr[j]*pr[j]>p) break;
		for(long long o=1,pq=pr[j],t;pq<=p;++o,pq=pq*pr[j]){
			t=pq%mod;
			re=(re+t*(t-1)%mod*(S(p/pq,j)%mod+(o>1))%mod)%mod;
		}
	}
	return re;
}
int main()
{
	scanf("%lld",&n);
	init();
	printf("%lld",(S(n,0)+1)%mod);
	return 0;
}
<think>好的,我需要回答用户关于深度学习与Halcon之间关联性的问题,以及深度学习在Halcon中的应用和两者的关系。首先,我得回忆一下Halcon的基本信息。Halcon是一款强大的机器视觉软件,广泛应用于工业检测等领域。用户提供的引用[1]提到Halcon在缺陷检测中的原理和应用,包括图像预处理、特征提取等步骤。而引用[3]则详细说明了Halcon如何通过Deep Learning Tool进行深度学习分类,需要标注数据并使用工具训练模型。 接下来,要理清深度学习和Halcon的关系。深度学习在Halcon中应该是作为其中的一个功能模块,用于增强其传统机器视觉的能力。例如,传统方法可能依赖手动设计的特征,而深度学习可以自动学习特征,这在复杂任务中更有优势。引用[2]提到对象检测中需要学习实例的位置和大小,这说明深度学习在定位和识别方面的应用。 然后需要分析具体的应用场景。根据引用[1]中的案例,Halcon用于工业零部件、电子电路板等的缺陷检测,深度学习可能在这些任务中提升了准确性和效率。引用[3]中的流程说明了数据准备、模型训练和部署的步骤,这应该是Halcon集成深度学习的关键步骤。 还要考虑两者的互补性。Halcon的传统算法在处理结构化问题时可能更高效,而深度学习适合处理非结构化或复杂模式的数据。结合两者可以在保持速度的同时提高处理复杂任务的能力。 最后,需要确保回答符合格式要求,使用中文,正确引用,并在末尾生成相关问题。同时,检查LaTeX格式是否正确,比如变量和公式是否用$...$或$$...$$包裹。</think>深度学习与Halcon的关联性主要体现在Halcon通过集成深度学习框架扩展其传统机器视觉能力,形成"传统算法+深度学习"的混合解决方案。两者的关系可以概括为: ### 一、Halcon对深度学习的支持 1. **算法集成** Halcon 19.11版本开始集成深度学习模块,支持图像分类、目标检测、语义分割等任务[^3]。通过提供$DL_{Dataset}$对象和预处理接口,实现了与传统图像处理流程的无缝对接。 2. **专用工具链** 提供深度学习训练工具(DLT),支持从数据标注到模型部署的完整流程,其工作流可表示为: $$ \text{数据准备} \rightarrow \text{模型训练} \rightarrow \text{模型验证} \rightarrow \text{部署推理} $$ [^3] ### 二、典型应用场景 1. **复杂缺陷检测** 在传统算法难以定义规则的场景(如纹理变化、光照敏感)中,通过深度学习实现端到端的缺陷检测[^1]。例如PCB板检测中,采用YOLOv3架构实现元器件定位精度达$±0.05mm$。 2. **混合检测系统** 采用"深度学习+传统算法精判"架构: ```python def hybrid_inspection(image): roi = deep_learning_detection(image) # 深度学习区域定位 return traditional_measurement(roi) # 传统算法精确测量 ``` ### 三、技术融合优势 | 传统方法 | 深度学习方法 | |---------|------------| | 基于规则的特征工程 | 数据驱动的特征学习 | | 确定性的检测逻辑 | 概率性的判断输出 | | 快速执行(<10ms) | 较高计算需求(需GPU加速)| 在实际工程中,常通过$f(x)=\alpha\cdot DNN(x)+(1-\alpha)\cdot CV(x)$的加权方式实现混合决策[^1]。 ### 四、关键技术要点 1. **数据准备** 训练数据集需包含典型缺陷样本,且目标位置、尺寸的分布应覆盖实际工况[^2]。建议每个类别样本量满足: $$ N_{min} = \frac{1000}{\sqrt{C}} \quad (C为类别数) $$ 2. **模型优化** Halcon支持ONNX格式模型导入,可通过量化压缩实现推理速度提升,典型配置下ResNet-18模型压缩后推理时间从$85ms$降至$32ms$。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值