数论 工具 线性筛

由于做莫反题需要大量的基础函数知识,于是有了这篇文章将我做到的函数都记录下来。

持续施工中。


约数和函数 σ

定义:σ(x)=d|xd

证其为积性函数:

x=piai,设 dx 的质因数个数,那么发现:

σ(x)=i1=0a1i2=0a2id=0adp1i1p2i2pdid=i1=0a1p1i1i2=0a2p2i2id=0adpdid=i=1dj=0aipij

我们发现当 d=1 时,σ(x)=i=0a1p1i,即上述式子可以转化为:

σ(x)=i=1dσ(piai)

推广可得:

σ(a×b)=σ(a)σ(b)gcd(a,b)=1

证毕。

接下来考虑如何线性筛。考虑我们当前的数 i,令其最小的质因子为 p。由积性函数可知,我们需要先使两个数 a,b 互质,再由 σ(a×b)=σ(a)σ(b) 转移。那么我们若想从 σ(i) 转移至 σ(i×p),需要先将 i 中所有的质因子 p 除掉,转移式子即为 σ(i×p)=σ(ipa1)σ(pa1+1)。用 lowi 维护 σ(pa1),那么 low 的转移有 lowi×p=lowi×p+1,此时 σ 的转移有 σ(i×p)=σ(i)lowi×lowi×p

实现中,当出现 imodpj=0 的情况就用上述方法转移,否则 σi×pj 直接用积性函数性质求,lowi×pj 的值等于 σ(pj),因为如果此时 i 中有比 pj 更小的质因子的话,早在前面就会被筛出来然后 break 掉。

因为 σo 挺像,所以在代码中 oi 表示 σ(i)

int pri[N],tot,o[N],low[N];
bool vis[N];
void Wprepare()
{
	o[1]=1;
	for(int i=2;i<=N;i++)
	{
		if(!vis[i]) pri[++tot]=i,o[i]=low[i]=i+1;
		for(int j=1;j<=tot;j++)
		{
			if(i*pri[j]>N) break;
			vis[i*pri[j]]=1;
			if(i%pri[j]==0)
			{
				low[i*pri[j]]=low[i]*pri[j]+1;
				o[i*pri[j]]=o[i]/low[i]*low[i*pri[j]];
				break;
			}
			low[i*pri[j]]=pri[j]+1;
			o[i*pri[j]]=o[i]*o[pri[j]];
		}
	}
}

例题是 [SDOI2014]数表,莫反部分不难,难点在理解如何筛约数和以及动态维护某个函数前缀和,练习 σ 函数的好题。

posted @   Ratio_Y  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示