杜教筛
推导过程
设现在要求积性函数 f(x) 的前缀和 S(x)。
用取整函数 [x] 表示下取整 ⌊x⌋,太懒了。
我们再构造一个函数 g(不需要积性),考虑 f∗g 的前缀和:
i=1∑n(f∗g)(i)=i=1∑nd∣i∑f(di)g(d)=d=1∑ni=1∑[dn]f(i)g(d)=d=1∑ng(d)S([dn])
观察得:
g(1)S(n)=i=1∑ng(i)S([in])−i=2∑ng(i)S([in])=(f∗g)(n)−i=2∑ng(i)S([in])
由于第一项本身是有一个 S(n) 的,现在我们利用上面的构造把 S(n) 去掉后,后面的一项就只需要我们求出 n 项 S 的值即可。
S(n)=g(1)(f∗g)(n)−∑i=2ng(i)S([in])
g 为积性函数时 g(1)=1:
S(n)=(f∗g)(n)−i=2∑ng(i)S([in])
所以杜教筛把难点规约到了一个点:
- 找到 g 使得 g 和 f∗g 的前缀和易求。
不会分析复杂度,但可以证明:预处理 Θ(n32) 项时,复杂度为 Θ(n32)。
P4213 【模板】杜教筛
T 次求 ∑i=1nφ(i) 和 ∑i=1nμ(i)。
T≤10,n≤231。
μ∗I=ϵ,φ∗I=id
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| auto DJ=[](auto &&DJ,ll n,auto &mp,auto &&Sf,auto &&Sg,auto &&S)->ll{ if(n<=B) return Sf[n]; if(mp.count(n)) return mp[n]; ll &ans=mp[n]=S(n); for(ll l=2,r;l<=n;l=r+1) { r=n/(n/l); ans-=(Sg(r)-Sg(l-1))*DJ(DJ,n/l,mp,Sf,Sg,S); } return ans; }; main: printf("%lld %lld\n", DJ(DJ,n,mp_phi,phi,[](ll n){return n;},[](ll n){return n*(n+1)/2;}), DJ(DJ,n,mp_mu,mu,[](ll n){return n;},[](ll n){return 1;}) );
|
P3768 简单的数学题
求:
i=1∑nj=1∑nij(i,j)
n≤1010。
略去复杂的莫反过程,我们要快速求 ∑x=1nx2φ(x),设 f(x)=x2φ(x)。
有意思的一点是:idcg∗idc=idc(g∗I)。
d∣x∑dcg(d)(dx)c=xcd∣x∑g(d)I(dx)
利用这个技巧,我们构造 g(x)=x2,则 f∗g=id2(φ∗I)=id3。
推导过程略去,∑x=1nx3=4n2(n+1)2。
考场上急需自然数幂和的公式实在不行就打个高斯消元。
注:整除分块套杜教筛跑 1010 是没有任何问题的,因为杜教筛会计算 n,[2n],[3n],⋯,所以整除分块其实只是在查表而已。
同理,这告诉我们,杜教筛套杜教筛(即 ∑f∗g 与 ∑g 也使用杜教筛来算)是复杂度不变的!
所以建议任何情况下使用杜教筛都用哈希表记录计算过的值。
补一下反演过程:利用欧拉反演我们知道 ∑d∣xφ(d)=x,还有一个冷知识是 ∑i=1ni3=(∑i=1ni)2=4n2(n+1)2。
===i=1∑nj=1∑nij(i,j)i=1∑nj=1∑nijk∣(i,j)∑φ(k)k=1∑nk2φ(k)i=1∑n/kij=1∑n/kjk=1∑nk2φ(k)(2(n/k)(n/k+1))2
到这一步已经能算了,你喜欢的话也可以接着用那个冷知识再化一步。
Powerful Number 筛
通常简记为 PN 筛,是杜教筛的一种扩展。
Powerful Number:每个质因子的幂次都 ≥2 的数,我喜欢把其构成的集合记作 PN(懒得打)。
性质:∣PN∩[1,n]∣=O(n)。
显然 x=a2b3⟺x∈PN,考虑把每个奇数次质因子扔三个到 b 里,剩下的和偶数次的扔到 a 里,枚举 a 可得:
Oa=1∑n(a2n)31=O(∫1n(x2n)31dx)=O(n)
求出 PN∩[1,n] 只需要暴力搜索质因数组合即可。
设我们要求前缀和的积性函数是 f(x),我们构造两个积性(狄利克雷卷积关于积性函数是封闭的)函数 g,h 满足 f=g∗h,且满足以下条件:
- ∀p∈P,f(p)=g(p)。
那么由于 ∀p∈P,f(p)=g(p)h(1)+g(1)h(p),可得 h(1)=1,h(p)=0。
由于 h 是积性函数,所以只有在 x∈PN 处 h(x) 有可能不为 0。
记 F(x)=∑i=1xf(i),G(x)=∑i=1xg(i),则:
F(n)=i=1∑n(g∗h)(i)=ij≤n∑g(j)h(i)=i=1∑nh(i)j=1∑[in]g(i)=i∈[1,n]∩PN∑h(i)G([in])
放下 G([in]) 不管,我们还需要求出 h(x∈PN)。
由于积性函数,其实质就是要求 h(pk),p∈P。
外层枚举是 Θ(n) 的,里面的 G 根据杜教筛特性只需求一次,Θ(n32),我们就求出了这种积性函数的前缀和。
特别的,若 G 容易计算,则该算法复杂度为 Θ(n)。
G 不容易计算时使用杜教筛,由于我们要用到的是其块筛,所以时间复杂度就是 Θ(n2/3)。