51nod 最大公约数 & 最小公倍数
2016-11-10 13:28
218 查看
之前学习杜教筛的时候,把 φ 和 μ 的前缀和两道题做过之后就没有再深入学习…NOI D1T3 看出来是杜教筛但是不会推只好做一个被唾弃的暴力选手…越来越觉得自己数论姿势太naive,所以补一补稍稍高端的知识。。。从刷经典题开始吧
要计算 f(i) 的前缀和(记为 F(i) ),考虑构造新的函数 g(i),使得 h=f∘g 的前缀和易于计算,那么我们有:
∑i=1nh(i)=∑i=1n∑ab=if(a)×g(b)=∑ab≤nf(a)×g(b)=∑b=1ng(b)×F(⌊nb⌋)
这里蕴含着一个关于 F(n) 的递推式,如果能快速计算 ∑ni=1h(i) 和 g(i) 的值,同时预处理 i≤n23 的 F(i),那么 F(n) 的计算可以被优化到 O(n23)
sol:
我们令 A(n)=∑ni=1(i,n),则答案等于 2×∑ni=1A(i)−∑ni=1i,这个分 i<j, i=j, i>j 讨论就能得出。
现在的问题是:如何快速计算 A(n) 的前缀和?
考虑化简 A(n),枚举 (i,n),我们有:
A(n)=∑d|nd×φ(nd)
显然这是个积性函数,并且知道它是 id 和 φ 的 Dirichlet 卷积,因为我们有:
φ=id∘μ
所以
id∘φ=id∘id∘μ
id∘φ∘1=id∘id
如果能够快速计算 id∘id 的前缀和,那么套用杜教筛,就能快速算出 A(n) 的前缀和。
记 A(n) 的前缀和为 S(n),id∘id 的前缀和为 H(n)
H(n)=∑i=1ni⌊ni⌋(⌊ni⌋+1)
这个显然是可以分块计算的。
使用杜教筛,我们总共需要计算 O(n√) 项 S(i) ,可以使用线性筛预处理出来 i≤n23 的S(i)。对于每一个 i>n23 的 S(i),我们 O(i√) 地计算它对应的 H(i)。因为我们计算 S(i) 时需要枚举 O(i√) 个 更小的 S(j),而计算 H(i) 的时间消耗也是 O(i√)。所以暴力计算这些 H(i) 不会使复杂度的阶升高,可以保证总的时间复杂度为 O(n23)
题外话:用这种做法交上去,最慢的点大概需要 2.3s 左右。A掉之后我去观摩了一下 1s 的神牛们的写法,发现非常 excited :
注意到:
S(n)=∑i=1n∑j|ij×φ(ij)=∑ij≤ni×φ(j)=∑i=1ni∑j=1⌊ni⌋φ(j)
于是按照 ⌊ni⌋ 分块计算一个 φ(i) 的前缀和就好了。。。我真是思博啊。。。
sol :
同样的,考虑计算 ∑ni=1[i,n],记为 A(n),同样的枚举 (i,n):
A(n)=n∑d|n∑(i,nd)=1i
注意到 n>1 时,”小于n且与n互质的数” 的和为 n×φ(n)2,对于 n=1 的情况特殊讨论,上式又可以简化为:
A(n)=n2∑d|nd×φ(d)+n2
后一项的前缀和即为 n×(n+1)4,以下讨论式子前一项的做法:
记 f(n)=n∑d|nd×φ(d),f(n) 的前缀和为 F(n)。考虑如何计算 F(n)
把 n “分配” 到和式中去,我们有:
f(n)=∑ab=na2φ(a)×b
注意到这是 id2⋅φ 和 id 的 Dirichlet 卷积,我们进一步地推导:
注意到 (id2⋅φ)∘id2=id3,即:
∑ab=na2φ(a)×b2=n2∑a|nφ(a)=n3
那么我们有:
id2∘(id2⋅φ)∘id=id3∘id
同样地,我们记 id3∘id 的前缀和为 H(n),那么:
H(n)=∑i=1i∑j=1⌊nd⌋j3
这个也可以分块计算,同上一题的复杂度分析,这道题我们也能得到一个 O(n23) 的做法。
前置技能(杜教筛)简介:
我们记 f∘g 表示数论函数 f 和 g 的 Dirichlet 卷积,下同。要计算 f(i) 的前缀和(记为 F(i) ),考虑构造新的函数 g(i),使得 h=f∘g 的前缀和易于计算,那么我们有:
∑i=1nh(i)=∑i=1n∑ab=if(a)×g(b)=∑ab≤nf(a)×g(b)=∑b=1ng(b)×F(⌊nb⌋)
这里蕴含着一个关于 F(n) 的递推式,如果能快速计算 ∑ni=1h(i) 和 g(i) 的值,同时预处理 i≤n23 的 F(i),那么 F(n) 的计算可以被优化到 O(n23)
最大公约数之和V3
题意:给定 n,计算 ∑ni=1∑nj=1(i,j)。(n≤1011)。sol:
我们令 A(n)=∑ni=1(i,n),则答案等于 2×∑ni=1A(i)−∑ni=1i,这个分 i<j, i=j, i>j 讨论就能得出。
现在的问题是:如何快速计算 A(n) 的前缀和?
考虑化简 A(n),枚举 (i,n),我们有:
A(n)=∑d|nd×φ(nd)
显然这是个积性函数,并且知道它是 id 和 φ 的 Dirichlet 卷积,因为我们有:
φ=id∘μ
所以
id∘φ=id∘id∘μ
id∘φ∘1=id∘id
如果能够快速计算 id∘id 的前缀和,那么套用杜教筛,就能快速算出 A(n) 的前缀和。
记 A(n) 的前缀和为 S(n),id∘id 的前缀和为 H(n)
H(n)=∑i=1ni⌊ni⌋(⌊ni⌋+1)
这个显然是可以分块计算的。
使用杜教筛,我们总共需要计算 O(n√) 项 S(i) ,可以使用线性筛预处理出来 i≤n23 的S(i)。对于每一个 i>n23 的 S(i),我们 O(i√) 地计算它对应的 H(i)。因为我们计算 S(i) 时需要枚举 O(i√) 个 更小的 S(j),而计算 H(i) 的时间消耗也是 O(i√)。所以暴力计算这些 H(i) 不会使复杂度的阶升高,可以保证总的时间复杂度为 O(n23)
题外话:用这种做法交上去,最慢的点大概需要 2.3s 左右。A掉之后我去观摩了一下 1s 的神牛们的写法,发现非常 excited :
注意到:
S(n)=∑i=1n∑j|ij×φ(ij)=∑ij≤ni×φ(j)=∑i=1ni∑j=1⌊ni⌋φ(j)
于是按照 ⌊ni⌋ 分块计算一个 φ(i) 的前缀和就好了。。。我真是思博啊。。。
最小公倍数之和 V3
题意:给定 n,计算 ∑ni=1∑nj=1[i,j]。(n≤1011)。sol :
同样的,考虑计算 ∑ni=1[i,n],记为 A(n),同样的枚举 (i,n):
A(n)=n∑d|n∑(i,nd)=1i
注意到 n>1 时,”小于n且与n互质的数” 的和为 n×φ(n)2,对于 n=1 的情况特殊讨论,上式又可以简化为:
A(n)=n2∑d|nd×φ(d)+n2
后一项的前缀和即为 n×(n+1)4,以下讨论式子前一项的做法:
记 f(n)=n∑d|nd×φ(d),f(n) 的前缀和为 F(n)。考虑如何计算 F(n)
把 n “分配” 到和式中去,我们有:
f(n)=∑ab=na2φ(a)×b
注意到这是 id2⋅φ 和 id 的 Dirichlet 卷积,我们进一步地推导:
注意到 (id2⋅φ)∘id2=id3,即:
∑ab=na2φ(a)×b2=n2∑a|nφ(a)=n3
那么我们有:
id2∘(id2⋅φ)∘id=id3∘id
同样地,我们记 id3∘id 的前缀和为 H(n),那么:
H(n)=∑i=1i∑j=1⌊nd⌋j3
这个也可以分块计算,同上一题的复杂度分析,这道题我们也能得到一个 O(n23) 的做法。
相关文章推荐
- Great Common Divisor & Least Common Multiple(最大公约数和最小公倍数)
- Java学习--最大公约数 && 最小公倍数
- Great Common Divisor & Least Common Multiple(最大公约数和最小公倍数)
- 数论(1):最大公约数和最小公倍数(Gcd&Lcm)
- HDU-1019-Least Common Multiple( 最大公约数 && 最小公倍数 && GCD )
- Python入门练习0005:输出最大公约数 & 最小公倍数
- POJ 1006 && 剩余定理 && 最小公倍数最大公约数
- 最大公约数 & 最小公倍数 计算
- 求m,n的最小公倍数和最大公约数m>n
- (温故而知新) 最小公倍数最大公约数的 C实现
- [备忘]求两数最大公约,最小公倍数
- 求两个数的最大公约数 最小公倍数
- C++ 实现最大公约数 最小公倍数
- 输入两个正整数a,b 求其最大公约数和最小公倍数
- 最大公约数和最小公倍数
- 最大公约数和最小公倍数
- 最大公约数/最小公倍数-算法
- 最大公约数 与 最小公倍数
- [数论]数论的基础知识——最大公约数、最小公倍数
- 最小公倍数和最大公约数之小结