数论筛法小记

会挖坑,好让复习的时候长脑子。

很多证明只是提两句,因为给自己看,以免复习时没有思路。

以下所有 p 都是质数,即 pP,同时默认均为正整数。

基础(Base)

唯一分解定理(算术基本定理):

(1)n>1,n=i=1kpiti

后面默认都分解了。

积性函数:

(2)xy,f(xy)=f(x)f(y)

完全积性函数:

(3)x,y\N+,f(xy)=f(x)f(y)

完全积性函数出现的比较少,不过积性函数也较好处理,可以线性筛。

经典的积性函数:

  • φ:欧拉函数。有性质 φ(n)=npk1pkn=dnφ(d)

    第一个考虑 φ(pt) 的取值,发现是 pt1(p1) 就很好说明。

    第二个考虑 1n,2n,,nn 这一串数的个数,化成最简分数来算。

  • μ:莫比乌斯函数。原始定义是 i=1nμ(i)=[n=1]

    根据定义可得:

μ(x)={(1)k,pn,p2n0,otherwise.

  • dσσk:约数个数函数 与 约数和函数 及 除数函数。

    其实 d 就是 σ0……

    表述可以是:σk(n)=dndk

一些比较牛逼的完全积性函数:

  • ϵ,依夫瑟洛!:狄利克雷卷积下的单位元,ϵ(n)=[n=1]
  • I:单位函数,I(n)=1
  • IdIdk:就是走个形式,Idk(n)=nk

别的先不谈,考虑怎么算积性函数。

简单筛(Sieve base)

计算原理

其实说筛之前应该先看一下积性函数的计算原理。

由于算术基本定理,任意数都可以表为若干个质数的次幂乘积。

因此我们只要分解 x,就可以根据积性函数的性质乘出 f(x)

由于分解难,往往是 O(n) 的复杂度,当然有一些随机算法能做到更优。

然而另一种思路是主动去凑 n,这在要求出 1nf 的值时就会更快。

这样就成了筛法。

线性筛。

埃筛 is too naive。

线性筛使得每个数字只被自己的最小质因子筛一次,过程如下:

Note: This is not pseudocode!
- If i is a prime
  - Add i into the P
- For all pri in P
  - Calc x=i*p
  - if p is a divisor of i
    * Calc x by p and i,then break
  - else f(x)=f(i)*f(p)

关键步骤在 * 一句,我们需要根据 pi 算出 x=ip 的值,而此时 i 中已经含有至少一个 p

可以使用无脑做法:f(x)=f(ipt)f(pt),显然可知 iptpt,正确性有保障。

注意像 x=pt 这样形式的情况要特别算。

这个基本就是线性筛积性函数的普适做法,感觉其实非常地简单但我当初就是听不懂。

狄利克雷卷积(Dirichlet Convolution)

狄利克雷卷积(以下简称卷积),定义如下:

h=fg,则

h(n)=dnf(d)g(nd)=dng(d)f(nd)

卷积满足交换律:fg=gf

同时满足结合律:(fg)h=f(gh)

一些常见的卷积:

  • ϵf=f
  • Iμ=ϵ
  • IdkI=σk
  • Iφ=Id
  • Idφ=μ

上面这些都可以拆式子得到。

比较重要的,卷积结合点乘的特殊规律:

(fg)(fh)=f(gh),要求 f 是完全积性函数。

考虑证明:

(4)(fg)(fh)(n)=dn(fg)(d)(fh)(nd)(5)=dnf(d)f(nd)g(d)h(nd)(6)=dnf(n)g(d)h(nd)(7)=f(n)dng(d)h(nd)(8)=f(n)(gh)(n)

显然成立。

整除分块(Sqrt Decomposition)

现在补充这个 trick。

考虑一个形如:i=1nf(i)g(ni) 的式子。

不难发现,g(ni) 这一部分的值在一段内是相同的。

那么能否拆成若干段来加速?

  • 对于 inni 的取值只有 O(n) 种。
  • 对于 i>nni<n,因此取值也只有 O(n) 种。

枚举每一段左右端点,取另一函数区间和(可用前缀和相减得到),乘上即可。

然后怎样根据 l 算出另一端点 r

不难发现,由于 nl=nr,可得 rnln

然后分完一整段则是 r 最大,那么由 rnnl,可知 r=nnl

代码如下 (放弃了鬼畜的流程表述)

for(int l=1,r;l<=n;l=r+1)
	r=(n/(n/l)),ans=(sum[r]-sum[l-1])*func(n/l);

扩展:若存在 nm 两个范围,即形如:i=1minn,mf(i)g(ni)h(mi),则每一块为:[i,minnni,mmi],且块的数量是 O(n+m) 级别的。

这个东西用处很多,比如在能快速求某一函数前缀和,或 O(n) 预处理后回答多次询问等情形。

杜教筛!(Du)

杜教筛用于在亚线性时间内求积性函数前缀和。

思路:构造 h=fg,其中 f 是欲求前缀和的函数。

Sff 前缀和,写一写:

(9)Sh(n)=i=1nh(i)(10)=i=1ndig(d)f(id)(11)=d=1ng(d)di,inf(id)(12)=d=1ng(d)k=1ndf(k)(13)=d=1ng(d)Sf(nd)

不难发现形成了递归式,变一下式子即可得到 Sf(n)

(14)Sh(n)=d=2ng(d)Sf(nd)+g(1)Sf(n)(15)g(1)Sf(n)=Sh(n)d=2ng(d)Sf(nd)(16)Sf(n)=Sh(n)d=2ng(d)Sf(nd)g(1)

然后运用整除分块,即可直接做。

需要 g 能快速查单点,h 能快速算前缀和 (有时或可筛套筛?)

复杂度我不会证,似乎要用到微积分,CSP 完了学一下。

如果预处理前 n23 项的值,则复杂度是 n23 的;否则为 n34

不要求是积性函数,能卷就行。

Trick

也许是重点。


(17)i=1ndif(d)g(id)(18)=d=1ndi,inf(d)g(id)

这种情况可以把 f(d) 提到外层求和,然后内层因为顺序无关,而 k=id 遍取 1nd 中所有整数(考虑 kd=i,in,可以解出 k 的范围),故可化为:

(19)=d=1nf(d)k=1ndg(k)


(20)i=1nj=1nσ0(ij)(21)=i=1nj=1nd1i,d1nd2j,d2n[gcd(d1,d2)=1]

这个推导在直观上很对,但不难发现直观理解出来,枚举的量既有重又有漏。

但是我们考虑 pt1ipt2jpt3d,dij,不妨做这样的钦定:

  • t3t1,钦定全部用 i 中的 p;此时 d1 含有因子 pd2 不含。
  • t3>t1,钦定用完 i 中的 p,然后使用 j 中的 t3t1p;此时 d2 含有因子 p,并强制令 d1 不含。

也就是说当 d1 不含因子 pd2 含有时,意味着 d1 提供 i 的所有因子 pd

两种情况下都做到了 gcd(d1,d2)=1,同时保证了对于 d 任意因子 p 的所有个数方案都可达。

故上式正确,同时也可解释为何在算约数和时不能直接套用此法。

posted @   LQ636721  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示