模板:杜教筛(莫比乌斯反演、数论)

所谓杜教筛,就是dms教给我们的筛

(逃)

前言

与其说算法,不如说是技巧。
可以在低于线性的时间复杂度(准确的说是 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32))内完成对积性函数的前缀和计算。

解析

考虑求函数 f f f 的前缀和:
S ( n ) = ∑ i = 1 n f ( i ) S(n)=\sum_{i=1}^nf(i) S(n)=i=1nf(i)
寻找另一个函数 g g g,设 h = f ∗ g h=f*g h=fg,那么有:
∑ i = 1 n h ( i ) = ∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) = ∑ d = 1 n g ( d ) ∑ i = 1 ⌊ n d ⌋ f ( i ) = ∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) \sum_{i=1}^nh(i)=\sum_{i=1}^n\sum_{d|i}g(d)f(\frac i d)\\=\sum_{d=1}^ng(d)\sum_{i=1}^{\lfloor\frac n d\rfloor}f(i)\\=\sum_{d=1}^ng(d)S(\lfloor\dfrac n d\rfloor) i=1nh(i)=i=1ndig(d)f(di)=d=1ng(d)i=1dnf(i)=d=1ng(d)S(dn)
尝试凑出 S ( n ) S(n) S(n):
g ( 1 ) S ( n ) = ∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) = ∑ d = 1 n h ( d ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) g(1)S(n)=\sum_{d=1}^ng(d)S(\lfloor\dfrac n d\rfloor)-\sum_{d=2}^ng(d)S(\lfloor\dfrac n d\rfloor)\\=\sum_{d=1}^nh(d)-\sum_{d=2}^ng(d)S(\lfloor\dfrac n d\rfloor) g(1)S(n)=d=1ng(d)S(dn)d=2ng(d)S(dn)=d=1nh(d)d=2ng(d)S(dn)
后面的 S S S 就可以递归求解了。

时间复杂度

按照上面的式子,可以写出时间复杂度的递推式:
T ( n ) = O ( n ) + ∑ i = 2 n ( T ( i ) + T ( n i ) ) T(n)=O(\sqrt n)+\sum_{i=2}^{\sqrt n}(T(i)+T(\frac n i)) T(n)=O(n )+i=2n (T(i)+T(in))
由于再往下递归就是高阶小量,我们只需要展开一层:
T ( n ) = O ( n ) + ∑ i = 2 n ( O ( i ) + O ( n i ) ) T(n)=O(\sqrt n)+\sum_{i=2}^{\sqrt n}(O(\sqrt i)+O(\sqrt \frac n i)) T(n)=O(n )+i=2n (O(i )+O(in ))
由于 O ( i ) + O ( n i ) ≥ O ( 2 n ) = O ( n 1 4 ) O(\sqrt i)+O(\sqrt \frac n i)\ge O(2\sqrt{\sqrt n})=O(n^{\frac 1 4}) O(i )+O(in )O(2n )=O(n41),所以总的复杂度大概是 O ( n 3 4 ) O(n^{\frac 3 4}) O(n43)

考虑先用线性筛预处理出一部分前缀和。
由于算法本身根号分治就有 O ( n ) O(\sqrt n) O(n ),所以不妨设预处理的范围 m > n m>\sqrt n m>n
那么时间复杂度就变成了:
T ( n ) = O ( m ) + O ( n ) + ∑ i = 2 ⌊ n m ⌋ T ( ⌊ n i ⌋ ) = O ( m ) + O ( n ) + ∑ i = 2 ⌊ n m ⌋ O ( ⌊ n i ⌋ ) = O ( m ) + O ( n ) + ∫ 0 n m n x = O ( m ) + O ( n ) + f ( n m ) ( f ( x ) = n x ) = O ( m ) + O ( n ) + O ( n m ) ≥ O ( n 2 3 ) T(n)=O(m)+O(\sqrt n)+\sum_{i=2}^{\lfloor\frac n m\rfloor}T(\lfloor\frac n i\rfloor)\\=O(m)+O(\sqrt n)+\sum_{i=2}^{\lfloor\frac n m\rfloor}O(\sqrt{\lfloor\frac n i\rfloor})\\=O(m)+O(\sqrt n)+\int_0^{\frac n m}\sqrt{\frac n x}\\=O(m)+O(\sqrt n)+f(\frac n m)(f(x)=\sqrt{nx})\\=O(m)+O(\sqrt n)+O(\frac{n}{\sqrt m})\\\ge O(n^{\frac 2 3}) T(n)=O(m)+O(n )+i=2mnT(in)=O(m)+O(n )+i=2mnO(in )=O(m)+O(n )+0mnxn =O(m)+O(n )+f(mn)(f(x)=nx )=O(m)+O(n )+O(m n)O(n32)
m = n 2 3 m=n^\frac 2 3 m=n32 时取等。

应用

如何使用杜教筛呢?

举个例子:计算 ∑ i = 1 n μ ( i ) \sum_{i=1}^n\mu(i) i=1nμ(i)
我们把刚才的核心式子拿下来:

g ( 1 ) S ( n ) = ∑ d = 1 n h ( d ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) g(1)S(n)=\sum_{d=1}^nh(d)-\sum_{d=2}^ng(d)S(\lfloor\dfrac n d\rfloor) g(1)S(n)=d=1nh(d)d=2ng(d)S(dn)
首先,我们需要使 ∑ d = 1 n h ( d ) \sum_{d=1}^nh(d) d=1nh(d) 可以很容易的求出来,不然就没有意义了。
同时,我们最好也能让 g g g 函数简单一些。
想到: μ ∗ 1 = e \mu*1=e μ1=e
g = 1 , h = e g=1,h=e g=1,h=e,就很好的满足了我们的要求。
式子变成:
S ( n ) = 1 − ∑ d = 2 n S ( ⌊ n d ⌋ ) S(n)=1-\sum_{d=2}^nS(\lfloor\dfrac n d\rfloor) S(n)=1d=2nS(dn)
非常简洁,直接求解即可。
实现上,需要开一个 map 或者哈希表进行记忆化。

代码

ll getmu(int n){
	if(n<=w) return sum1[n];
	if(mp1.count(n)) return mp1[n];
	ll ans=1;
	for(ll l=2,r;l<=n;l=r+1){
		assert(n/l);
		r=n/(n/l);
		ans-=(r-l+1)*getmu(n/l);
	}
	return mp1[n]=ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值