杜教筛
嘟嘟嘟
tangjz orz
jiry_2 orz
任之洲 2016国家队论文 orz
概述
前置技能:莫比乌斯反演
可以在(O(frac{3}{4}))或(O(frac{2}{3}))复杂度完成数论函数(前缀和)的计算
一般形式
数论函数(f(n)),求
对于任意数论函数(g(n)),均满足
(Proof.)
- 注意枚举几倍的技巧:对于i*j=k,我们枚举了i和j
这样的话可以得到
通常情况(g(1)=1)
这个柿子可以整除分块
找到合适的(g)
如果能通过狄利克雷卷积构造一个更好计算前缀和的函数,且用于卷积的另一个函数也易计算,则可以简化计算过程
时间复杂度
假设计算出(ϕ(n))的复杂度为(T(n)),则有(T(n)=O(sqrt{n})+sum_{i=1}^{sqrt{n}}{T(i)+T(frac{n}{i})}),这里只展开一层就可以了,更深层的复杂度是高阶小量,所以有(T(n)=sum_{i=1}^{sqrt{n}}{O(sqrt{i})+O(sqrt{frac{n}{i}})}=O(n^frac{3}{4}))
预处理前k个的答案后,(T(n)=sum_{i=1}^{frac{n}{k}}{sqrt{frac{n}{i}}}=O(frac{n}{sqrt{k}})),(k=O(n^frac{2}{3}))时最优(T(n)=O(n^frac{2}{3}))
基本形式
- 基本形式只是为了简化思考,用一般形式找函数卷上均可以完成
就是说没大有用啦
一. 数论函数(f(n)),完全积性函数(g(n)),求
此时满足
(Proof.)
也就是说这种情况我们只要让另一个函数卷(1),完全积性函数直接当做我们找的函数。
二. 待填坑
简单的栗子
都是卷上(1)
一. 求(mu)的前缀和
二. 求(varphi)的前缀和
代码实现
使用记忆化搜索和哈希表
//这是phi前缀和。首先要线性筛预处理一部分。
namespace ha {
const int p = 1001001;
struct meow{int ne; ll val, r;} e[3000];
int cnt=1, h[p];
inline void insert(ll x, ll val) {
ll u = x % p;
for(int i=h[u];i;i=e[i].ne) if(e[i].r == x) return;
e[++cnt] = (meow){h[u], val, x}; h[u] = cnt;
}
inline ll quer(ll x) {
ll u = x % p;
for(int i=h[u];i;i=e[i].ne) if(e[i].r == x) return e[i].val;
return -1;
}
} using ha::insert; using ha::quer;
ll dj_sieve(ll n) {
if(n <= U) return phi[n];
if(quer(n) != -1) return quer(n);
ll ans = n%mo * ((n+1) %mo) %mo * inv2 %mo, r;
for(ll i=2; i<=n; i=r+1) {
r = n/(n/i);
mod(ans -= dj_sieve(n/i) * ((r-i+1) %mo) %mo);
}
insert(n, ans);
return ans;
}
栗子
一. 求 (sum_{i=1}^n sum_{j=1}^n lcm(i, j))
有两类做法。
一.变成积性函数求和的形式
首先进行化简
(ans = 2*A(n) - sum_{i=1}^n)
就是(f(n) = nsum_{dmid n}d cdot varphi(d)= id cdot ((id cdot varphi) * 1))的前缀和。
- 其中重要的一步在于使用欧拉函数的性质代入,而不是使用莫比乌斯函数代入
这里又有两种做法。
法一:
后面是可以整除分块的形式,我们只要处理出(i^2 cdot varphi(i)=(id^2 cdot varphi)(i))的前缀和(S(n))就行了
(id^2)是完全积性函数,满足杜教筛基本形式一,单独让(varphi)卷上(1),也变成(id)了。
或者直接卷上(id^2),效果相同
其中(sum_{i=1}^{n} i^3 = (frac{n(n+1)}{2})^2, sum_{i=1}^{n} i^2 = frac{n(n+1)(2n+1)}{6})
杜教筛的过程中计算了所有(S(lfloor frac{n}{i} floor)),可以和整除分块配合食用
法二:
把f外面的n拿进来
直接计算(f(n) = id cdot ((id cdot varphi) * 1) = (id^2 cdot varphi) * id)的前缀和。
卷上(id^2)
前部分的前缀和可以用整除分块解决
使用线性筛直接预处理S的前(n^{frac{2}{3}})项,只要预处理((id cdot varphi) * 1 = sum_{dmid n}d cdot varphi(d))就行了,因为是点乘比较好做。(p^c)的形式处理出来,剩下的保留最小质因子的幂次然后用积性。
二.使用莫比乌斯反演的套路
看abclzr的博客发现了这种做法:
套路推♂倒之后得到的柿子是:
我们只需用杜教筛计算(i sum_{dmid i} dcdot mu(d))的前缀和,然后与整除分块配合就行了(因为每次块的r的值也是一个(frac{n}{i})的值)。
就是要计算(f=(id^2 cdot mu) * id)的前缀和,卷上(id^2)后变成(f(n) = nsum_{dmid n}[d=1]=n)
上杜教筛就行了
预处理的话,可以用线性筛预处理(f'=sum_{dmid n}dcdot mu(d)),发现(f'=prod_i(1-p_i))
这样做的好处是可以处理n和m的情况
总结
找到一个函数卷上方便求
莫比乌斯反演的题目一般是约数和倍数互换 令D=de,这里一般是约数与几倍互换
TA:
对于d,e,D=d*e 三项贡献的这种,可以枚举D将其化为狄利克雷卷积,也可以枚举d和e化成带下取整的式子;一般来讲前者往往易于预处理,可以应付多组询问,后者则在单次询问中有优秀表现。