迪利克雷卷积
定义:f(n),g(n)是两个积性函数
(f∗g)(n)=∑d|nf(d)·g(nd)=∑d|nf(nd)·g(d)
性质:
1.交换律:f∗g=g∗f
2.结合律:(f∗g)∗h=f∗(g∗h)
3.分配律:(f+g)∗h=f∗h=g∗h
常用函数
1.元函数: ξ(n)=[n=1]
2.常数函数:1(n)=1
3.恒等函数:id(n)=n
4.欧拉函数:φ(n)=∑ni=1[gcd(i,n)=1]
性质:∑d|nφ(d)=n
5.莫比乌斯函数:
μ(n)={1n=10n包含相同质因子(−1)sn=p1p2…ps
性质:∑d|nμ(d)=[n=1]
6.莫比乌斯函数与欧拉函数的联系:
∑d|nμ(d)nd=φ(n)
常用卷积关系
1.∑d|nμ(d)=[n=1]⟺u∗1=ξ
2.∑d|nφ(d)=n⟺φ∗1=id
3.∑d|nμ(d)·nd=n⟺u∗id=φ
4.f∗ξ=f
5.f∗1≠f
6.f∗u∗1=f
证明
(μ∗1)(n)=∑d|nμ(d)·1(nd)=∑d|nμ(d)=[n=1]=ξ(n)
(φ∗1)(n)=∑d|nφ(d)·1(nd)=∑d|nφ(d)=[n=1]=id(n)
(μ∗id)(n)=∑d|nμ(d)·id(nd)=∑d|nμ(d)·nd=φ(n)
(f∗ξ)(n)=∑d|nf(d)·ξ(nd)=∑d|nf(d)·[nd=1]=f(n)
(f∗1)(n)=∑d|nf(d)·1(nd)=∑d|nf(d)
(f∗u∗1)(n)=(f∗(u∗1)(n))(n)=(f∗ξ)(n)=f(n)
杜教筛原理
用途:在低于线性时间里,高效率求一些积性函数的前缀和
原理:整除分块+迪利克雷卷积+线性筛
公式:g(1)S(n)=n∑i=1(f∗g)(i)−n∑i=2g(i)S(⌊ni⌋)
推导:∑ni=1(f∗g)(i)
=∑ni=1∑d|if(id)g(d)=∑ni=1∑nd=1[d|i]f(id)g(d)
=∑nd=1∑ni=1[d|i]f(id)g(d)=∑nd=1∑nid=1[d|id]f(idd)g(d)
=∑nd=1∑ndi=1f(i)g(d)=∑nd=1g(d)S(nd)
=g(1)S(n)+∑nd=2g(d)S(nd)
具体做法:
1.使用线性筛预处理出n较小时的s(n)来剪枝
2.使用哈希表来做记忆化剪枝
3.使用整除分块做递归
时间复杂度:O(n23)
杜教筛模板
以该题为例:
求s(n)=n∑i=1φ(i)
解:
因为
φ∗1=id,所以f=φ,g=1,f∗g=id
s(n)=∑ni=1id(i)−∑ni=21(d)s(ni)
=∑ni=1i−∑ni=2s(ni)=n(n+1)2−∑ni=1s(ni)
const int N=2e5+10;
// 线性筛所需
bool vis[N];
vector<ll> pri;
// 所需处理的函数
ll mu[N],phi[N];
map<ll,ll> mp_phi;
// 线性筛初始化
void init(){
phi[1]=1; // n=1时的函数取值
for(int i=2;i<N;i++) {
if(!vis[i]) {
pri.push_back(i);
phi[i]=i-1; //处理n为素数时的函数取值
}
for(int j=0;1ll*i*pri[j]<N;j++) {
vis[i*pri[j]]=true;
if(i%pri[j]==0) {
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
else {
phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
}
for(int i=1;i<N;i++) phi[i]+=phi[i-1];
}
ll Sphi(ll n){
if(n<N) return phi[n];
if(mp_phi[n]) return mp_phi[n];
ll ans=n*(n+1)/2;
for(ll l=2,r;l<=n;l=r+1) {
r=n/(n/l);
ans-=Sphi(n/l)*(r-l+1);
}
return mp_phi[n]=ans;
}
Orz