笔记:莫比乌斯反演
摘自peng-ym的博客
整除分块
\(\sum_{i=1}^n \lfloor {\frac n i} \rfloor\)
朴素 \(O(n)\) , 整除分块 \(O(\sqrt n)\)
显然有许多连续的 \(\lfloor {\frac n i} \rfloor\) 值是一样的。可以发现,每个块的最后一个数是 \(\frac n {\lfloor \frac n i\rfloor }\)
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
有时推出的柿子不一定是裸的板子,可能与一些积性函数相乘( \(\mu\),\(\phi\)...),
此时需要对这些函数统计前缀和,这样跳过一个区间时就乘上一个区间的函数值。(?)
积性函数&狄利克雷卷积
以后我也会卷啦!
积性函数:
定义:
如果 \(gcd(x,y)=1\) 并且 \(f(xy)=f(x)·f(y)\) 则 \(f(n)\) 是积性函数。
特别的,对于任意 \(x,y\) 满足 \(f(xy)=f(x)·f(y)\) 的是完全积性函数。
e.g.
完全积性
-
一元函数:\(\epsilon (x)=[x=1]\) 是积性函数的单位元(可以随便卷在一起和去掉)
-
常数函数:\(1(x)=1\) 好像也有用字母 \(I\) 的。
-
单位函数:\(id(x)=x\)
积性
-
欧拉函数:\(\phi(x)=\sum_{i=1}^x [gcd(x,i)=1]\)
-
约数个数函数:\(d(x)=\sum_{d|n} 1\)
-
约数和函数: \(\sigma(n)=\sum_{d|n} d\)
-
莫比乌斯函数:……
性质:
如果\(h(x)=f(x^p)\)或\(h(x)=f^p(x)\),\(f(x)\) 是积性函数,那么 \(h(x)\) 也是:
如果 \(f(x)\) 和 \(g(x)\) 是积性函数,那么 \(h(x)\) 也是:
狄利克雷卷积
定义:
两个数论函数 \(f\) 和 \(g\) 的狄利克雷卷积 \((f*g)\) 为
性质:
满足交换律和结合律和分配率。自己卷自己是自己。
莫比乌斯反演
莫比乌斯函数
-
符号:\(\mu\) .
-
定义:
\[ \mu(d)=\left\{ \begin{array}{rcl} 1 & & {d=1}\\ (-1)^k & & {d=\Pi_{i=1}^k\ p_i\ 且\ p_i\ 为互异素数时}\\ 0 & & {d\ 的一个质因子次数\ge 2}\\ \end{array} \right. \] -
性质:
- 对于任意 \(n\in {N}^+\),\(\mu*1=\epsilon\ (\sum_{d|n} \mu(d)=[n=1])\) 常用性质
考虑非0的 \(\mu(d)\) 的和。
设 \(n\)有 \(k\) 个质因子,有 \(2^k\) 个因子,有 \(C_{k,i}\) 个的有 \(i\) 个质因子,
\(ans=C(k,0)-C(k,1)+C(k,2)-C(k,3)+...=\sum_{i=0}^k (-1)^iC(k,i)\)
二项式定理: \((x+y)^n=\sum C(n,i)x^iy^{(n-i)}\)
\(ans=(-1+1)^k=0^k\)
得证。\(\mu\) 是 \(I\) 的狄利克雷逆
-
对于任意 \(n\in N^+\),
\[\sum_{d|n} \frac {\mu(d)} d=\frac {\phi(n)} n \]Proof
\[首先有结论\sum_{d|n} \phi(d)=n(id=\phi*I)\\ 证明:\\ \frac 1 n,\frac 2 n,\frac 3 n,...,\frac n n \\化简这些分数 分母是 d (d|n)\\ 每个分母d对应的分子个数就是 \phi(d) \]\[id=\phi*I\\ \phi=id*\mu\\ \phi(n)=\sum_{d|n} \mu(d)*\frac n d\\ \]
-
代码
void getmu(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]) { p[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt&&p[j]*i<=n;j++){ vis[p[j]*i]=1; if(i%p[j]==0) break; else mu[p[j]*i]=-mu[i]; } } }
\(O(n)\)
莫比乌斯反演
莫比乌斯反演定理
\(F(n)\) 和 \(f(n)\) 是定义在 \(N\) 上的两个函数,并且满足条件
有结论:
Proof:
\[\sum_{d|n}\mu(d)F(\lfloor\frac{n}{d}\rfloor)\\=\sum_{d|n}\mu(d)\sum_{i|\lfloor\frac{n}{d}\rfloor}f(i)\\ =\sum_{i|n}f(i)\sum_{d|\lfloor\frac{n}{i}\rfloor}\mu(d)\\=f(n) \]
Proof2:
噫!好!让我们用狄利克雷卷积来证明一下。
已知
\[F(n)=\sum_{d|n} f(d) \]求证
\[f(n)=\sum_{d|n} \mu(d)·F(\frac n d) \]\[转化一下:\\ 已知:\\ F(n)=\sum_{d|n} f(d)\\ F(n)=\sum_{d|n} f(d)·1(\frac n d)\\ F=f*1\\ 求证:\\ f(n)=\sum_{d|n} \mu(d)·F(\frac n d)\\ f(n)=\mu *F\\ 证明:\\ F*\mu=f*1*\mu=f*\epsilon=f\\ 比上面那坨好多了qwq \]
莫比乌斯反演有另一种可能更好用的形式:
条件:
结论:
证明:
令 \(k=\frac d n\)
\(f(n)=\sum_{k=1}^{inf} \mu(k)F(nk)=\sum_{k=1}^{inf} \mu(k) \sum_{nk|t} f(t)=\sum_{n|t} f(t) \sum_{k|\frac t n} \mu(k)\)
当且仅当 \(\frac t n =1\) ,即 \(t=n\) 时, \(\sum_{k|\frac t n}\mu(k)=1\)
∴ \(\sum_{n|t} f(t) \sum_{k|\frac t n}\mu (k)=f(n)\)
$F(n)=\sum_{n|d} f(d) $
\(f(n)=\sum_{n|d}\mu(\lfloor \frac{d}{n} \rfloor)F(d)\)
习题
LG2257 - YY的GCD
给定 \(N,M\) ,求 \(1\le x \le N,1\le y\le M\) 且 \(gcd(x,y)\) 为质数的 \((x,y)\) 有多少对?
\(ans=\sum_{x=1}^n \sum_{y=1}^m [gcd(x,y)=prime]\)
第一道莫反不会做 列完这个柿子就壮烈牺牲了。
设 \(f(d)\) 为 \(gcd(i,j)=d\) 的个数
\(F(n)\) 为 \(gcd(i,j)=n\) 和 \(n\) 的倍数的个数。
(套路)
\(f(d)=\sum_{x=1}^n \sum_{y=1}^m [gcd(x,y)=d]\)
\(F(n)=\sum_{n|d} f(d)=\lfloor \frac N n \rfloor \lfloor \frac M n \rfloor\)
\(f(n)=\sum_{n|d}\mu(\lfloor \frac{d}{n} \rfloor)F(d)\)
\(ans=\sum_{p\in prime} f(p)\)
\(ans=\sum_{p\in prime} \sum_{p|d}\mu(\lfloor \frac{d}{p} \rfloor)F(d)\)
\(ans=\sum_{p\in prime} \sum_{d=1}^{min(\frac n p,\frac m p)} \mu(d)F(dp)\)
\(ans=\sum_{p\in prime} \sum_{d=1}^{min(\frac n p,\frac m p)} \mu(d)\lfloor \frac n {dp} \rfloor \lfloor\frac m {dp} \rfloor\)
\(ans=\sum_{T=1}^{min(n,m)} \lfloor \frac n T \rfloor \lfloor \frac m T\rfloor \times(\sum_{t|T,t\in prime} \mu(\lfloor \frac T t\rfloor))\)
最后一坨东西可以预处理 前面那坨整除分块
void getmu(){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!fl[i]) p[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&p[j]*i<=N;j++){
fl[p[j]*i]=1;
if(i%p[j]==0) continue;
mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<=cnt;i++)
for(int j=1;p[i]*j<=N;j++)
f[p[i]*j]+=mu[j];//T=p[i]*j t=p[i]
for(int i=1;i<=N;i++) sum[i]=sum[i-1]+f[i];
return;
}//预处理前面那坨
long long solve(int a,int b){
long long ans=0;
for(int l=1,r;l<=a;l=r+1){
r=min(a/(a/l),b/(b/l));
ans+=1ll*(sum[r]-sum[l-1])*(a/l)*(b/l);
}
return ans;
}//预处理后面那坨
int main(){
int t; scanf("%d",&t);
getmu();
while(t--){
scanf("%d%d",&n,&m);
if(n>m) swap(n,m);
printf("%lld\n",solve(n,m));
}
return 0;
}
草,题解说入门的不适合做这题(
LG2522 - [HAOI2011]Problem b
\(n\) 次询问,每次询问有多少个数对 \((x,y)\) 满足 \(a\le x\le b,c\le y\le d\) 且 $gcd(x,y)=k $ 所有东西都是 \(5\times 10^4\)
草 这好像是前一题的低配啊,这确定没搞反吗。
void getmu(){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!fl[i]) p[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&p[j]*i<=N;j++){
fl[p[j]*i]=1;
if(i%p[j]==0) continue;
mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<=N;i++) sum[i]=sum[i-1]+mu[i];
return;
}
long long solve(int a,int b,int k){
if(a>b) swap(a,b);
long long ans=0;
for(int l=1,r;l<=a;l=r+1){
r=min(a/(a/l),b/(b/l));
ans+=1ll*(sum[r]-sum[l-1])*(a/(1ll*l*k))*(b/(1ll*l*k));
}
return ans;
}
int main(){
int t; scanf("%d",&t);
getmu();
while(t--){
int a,b,c,d,k;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
printf("%lld\n",solve(b,d,k)-solve(a-1,d,k)-solve(b,c-1,k)+solve(a-1,c-1,k));
}
return 0;
}
显然顺序搞反了。。
[LG3455 - POI2007]ZAP-Queries
倒序开题,双倍经验,这是好的。这是前一道题的前置题。是 \(a=1,b=1\) 的情况。
[LG3327 - SDOI2015]约数个数和
设 \(d(x)\) 为 \(x\) 的约数个数,给定 \(n,m\) ,求 \(\sum_{i=1}^n \sum_{j=1}^m d(ij)\)
void init(){
for(int i=1;i<=N;i++){
for(int l=1,r;l<=i;l=r+1){
r=i/(i/l);
s[i]+=1ll*(r-l+1)*(i/l);
}
}//预处理s
mu[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]) p[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&p[j]*i<=N;j++){
vis[i*p[j]]=1;
if(i%p[j]==0) continue;
mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<=N;i++) sum[i]=sum[i-1]+mu[i];
return;
}
int main(){
int t; scanf("%d",&t);
init();
while(t--){
int n,m; scanf("%d%d",&n,&m);
if(n>m) swap(n,m);
ll ans=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=1ll*(sum[r]-sum[l-1])*s[n/l]*s[m/l];
}//分块求
printf("%lld\n",ans);
}
return 0;
}
LG1829 [国家集训队]Crash的数字表格 / JZPTAB
求 \(ans=\sum_{i=1}^n \sum_{j=1}^m lcm(i,j)\) \(n,m\le 10^7\)
void init(){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){ mu[i]=-1; p[++cnt]=i; }
for(int j=1;j<=cnt&&p[j]*i<=N;j++){
vis[p[j]*i]=1;
if(i%p[j]==0) continue;
mu[p[j]*i]=-mu[i];
}
}
for(int i=1;i<=N;i++)
sum[i]=(sum[i-1]+1ll*mu[i]%mod*i%mod*i%mod)%mod;
return;
}
int calc(int x){ return (1ll*x*(x+1)/2)%mod; }
int main(){
scanf("%d%d",&n,&m);
if(n>m) swap(n,m);
init();
for(int d=1;d<=n;d++){
int a=n/d,b=m/d,ret=0;
for(int l=1,r;l<=a;l=r+1){
r=min(a/(a/l),b/(b/l));
ret=(ret+1ll*(sum[r]-sum[l-1])*calc(n/(d*l))%mod*calc(m/(d*l))%mod)%mod;
}
ans=(ans+1ll*ret*d%mod)%mod;
}
printf("%d\n",(ans+mod)%mod);
return 0;
}
SP5971 LCMSUM - LCM Sum
\(T\) 次询问,每次询问给定 \(n\) ,求 \(\sum_{i=1}^n lcm(i,n)\)
void init(){
phi[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]) phi[i]=i-1,p[++cnt]=i;
for(int j=1;j<=cnt&&p[j]*i<=N;j++){
vis[p[j]*i]=1;
if(i%p[j]==0){
phi[p[j]*i]=phi[i]*p[j];
break;
}
phi[p[j]*i]=phi[i]*(p[j]-1);
}
}
for(int i=1;i<=N;i++){
ll tmp=1ll*phi[i]*i/2;
if(i==1) tmp=1;
for(int j=1;j*i<=N;j++) f[j*i]+=tmp;
}
return;
}
int main(){
scanf("%d",&t);
init();
while(t--){
scanf("%d",&n);
printf("%lld\n",1ll*f[n]*n);
}
return 0;
}
咕咕咕