学习笔记——莫比乌斯反演
前言
时隔一年,学了点多项式基础,然后来搞搞数论。学一下颓柿子。
数论分块
是用莫反解决问题的基础。
形式:如果有式子 \(\sum\limits_{i=1}^ng(\lfloor\dfrac{n}{i}\rfloor)\) 需要求值,我们能在 \(O(\sqrt{n})\) 的复杂度内求出上面这个式子的值。即需要求的东西中需要有带整除的值,所以也叫整除分块。
考虑到当 \(n\) 很大的时候,我们这个 \(\lfloor\dfrac{n}{i}\rfloor\) 的取值是非常少的。可以证明取值不超过 \(2\sqrt{n}\) 个。
$\texttt{Proof}$
若 \(i\le\sqrt{n}\),那么就算每个 \(i\) 都有一个不同的 \(\lfloor\dfrac{n}{i}\rfloor\),那总数也不超过 \(\sqrt{n}\) 个。
若 \(i\ge\sqrt{n}\),那么有 \(\lfloor\dfrac{n}{i}\rfloor\le\dfrac{n}{i}\le\sqrt{n}\),所以也不超过 \(sqrt{n}\) 个。
综上,这样的取值不超过 \(2\sqrt{n}\) 个。
接下来我们需要一个性质:\(\lfloor\dfrac{\lfloor\frac{x}{a}\rfloor}{b}\rfloor=\lfloor\dfrac{x}{ab}\rfloor\)。
证明略。
然后就有如下结论:对于每个 \(\lfloor\dfrac{n}{i}\rfloor\) 相等的块,其左端点为 \(l\) 的话,右端点就是 \(\lfloor\dfrac{n}{\lfloor\frac{n}{l}\rfloor}\rfloor\)。
$\texttt{Proof}$
令 \(k=\lfloor\dfrac{n}{i}\rfloor\),有 \(\lfloor\dfrac{n}{i}\rfloor\le \dfrac{n}{i}\)。
则 \(\lfloor\dfrac{n}{k}\rfloor\ge\lfloor\dfrac{n}{\frac{n}{i}}\rfloor=i\)。所以最大的 \(i\) 就是 \(\lfloor\dfrac{n}{k}\rfloor=\lfloor\dfrac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)。
这样一来,代码就很好写了。
$\texttt{Code}$
void solve(){
ll n;cin>>n;
ll ans=0;
for(ll l=1,r;l<=n;l=r+1){
r=n/(n/l);ans+=(r-l+1)*(n/l);
}cout<<ans<<'\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;for(cin>>T;T--;)solve();
return 0;
}
$\texttt{Code}$
int main()
{
ll n,k,ans;
scanf("%lld%lld",&n,&k);ans=n*k;
for(ll l=1,r;l<=n;l=r+1){
if(k/l) r=min(k/(k/l),n);else r=n;
ans-=(l+r)*(r-l+1)/2*(k/l);
}printf("%lld\n",ans);
}
以及一个显然的结论:
前置知识
你需要会素数筛(好歹是线性筛吧),然后唯一分解定理。
然后是调和级数求和是 \(n\log n\) 也得知道。
数论函数
定义:若对于 \(a\bot b\),有 \(f(ab)=f(a)f(b)\),则 \(f(x)\) 为积性函数。
单位函数
任何函数卷积上这个函数都是那个函数本身。单位函数是积性的。
除数函数
\(\sigma_0{(x)}\) 为 \(x\) 的约数个数,\(\sigma_1{(x)}\) 为约数和,简称 \(\sigma(x)\)。除数函数也是积性的。
欧拉函数
内容比较多,主要是关于欧拉定理和欧拉筛的,\(\varphi(x)\) 表示小于 \(x\) 的与 \(x\) 互质的数的个数。
其中 \(p_i\) 表示 \(x\) 的第 \(i\) 个质因子。当然也可以用欧拉筛出欧拉函数。
幂函数
狄利克雷卷积
一种特殊的因数卷积。
是 \(f(x)\) 和 \(g(x)\) 的狄利克雷卷积,记做 \(h=f*g\)。
性质:满足结合律,并且如果 \(f,g\) 都是积性函数,那么 \(f*g\) 也是积性函数。
一些常见的卷积:\(\mu*1=\epsilon,Id=\varphi*1\)。
也就是:
莫比乌斯函数
这东西由于也是积性的,可以用线性筛求。
莫比乌斯反演
\(g=f*1\),则 \(g\) 是 \(f\) 的莫比乌斯变换。
那么 \(f\) 就是 \(g\) 的莫比乌斯逆变换。
莫比乌斯反演定理指出:\(g=f*1\Leftrightarrow f=g*\mu\)。
一些例题
题单中指出了莫比乌斯反演的三种形式,也就是最常见的三种。
Case1:
然后你整除分块搞一下就可以 \(O(\sqrt{n})\) 求了。
Case2:
然后和上面那个同理,最后
Case3:
接着令 \(T=kd\),则有:
P2568 GCD
本题要求:
然后暴力枚举直接做就好了。
$\texttt{Code}$
const int MAXN=1e7+10;
int mu[MAXN],pr[MAXN],p[MAXN],cnt,n;
void init(){
p[1]=1;mu[1]=1;
rep(i,2,n){
if(!p[i]) pr[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*pr[j]<=n;j++){
p[i*pr[j]]=1;
if(i%pr[j]){
mu[i*pr[j]]=-mu[i];
}else{mu[i*pr[j]]=0;break;}
}
}
}
int pre[MAXN];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;init();
rep(i,1,n) pre[i]=pre[i-1]+mu[i];
int ans=0;
rep(i,1,cnt){
int m=n/pr[i],cur=0;
for(int l=1,r;l<=m;l=r+1){
r=m/(m/l);cur+=(pre[r]-pre[l-1])*(m/l)*(m/l);
}ans+=cur;
}cout<<ans<<'\n';
return 0;
}
P1891 疯狂 LCM
题目要求:
令 \(f(x)=\sum\limits_{d|x}\varphi(d)\times d\),这是个积性函数,可以筛出来。
$\texttt{Code}$
const int MAXN=1e6+10;
int p[MAXN],pr[MAXN],cnt;
ll f[MAXN];
void init(){
f[1]=1;p[1]=1;
rep(i,2,MAXN-10){
if(!p[i]){pr[++cnt]=i,f[i]=1ll*i*(i-1)+1;}
for(int j=1;j<=cnt&&i*pr[j]<=MAXN-10;j++){
p[i*pr[j]]=1;
if(i%pr[j]) f[i*pr[j]]=f[i]*f[pr[j]];
else{f[i*pr[j]]=f[i]+(f[i]-f[i/pr[j]])*pr[j]*pr[j];break;}
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
init();
int T;for(cin>>T;T--;){
int n;cin>>n;
cout<<1ll*(n*f[n]+n)/2<<'\n';
}
return 0;
}
SP21615 NAJPWG - Playing with GCD
题目要求:
直接预处理就好了。
$\texttt{Code}$
const int MAXN=1e5+10;
int p[MAXN],pr[MAXN],phi[MAXN],cnt;
int ans[MAXN];
void init(){
phi[1]=1;p[1]=1;
rep(i,2,MAXN-10){
if(!p[i]) pr[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*pr[j]<=MAXN-10;j++){
p[i*pr[j]]=1;
if(i%pr[j]) phi[i*pr[j]]=phi[i]*phi[pr[j]];
else{phi[i*pr[j]]=phi[i]*pr[j];break;}
}
}rep(i,1,MAXN-10) ans[i]=ans[i-1]+i-phi[i];
}
void solve(int Cas){
int n;
cin>>n;
cout<<"Case "<<Cas<<": "<<ans[n]<<'\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
init();
int T;cin>>T;
rep(_,1,T) solve(_);
return 0;
}