莫比乌斯反演作为数论与组合数学中的重要内容,在学习莫反前请先具备一定数论与组合数学相关知识。
推荐阅读:https://blog.xecades.xyz/articles/DirichletConvolution/
本次课通过两道例题来介绍高级数论莫比乌斯反演在信息学竞赛中的考察。
莫比乌斯反演相关题型主要在于式子推导及变换处理。
本次课选取的题目不算难,以单独的莫比乌斯反演为主。
事实上,莫比乌斯反演还可再结合积性函数、Dirichlet卷积、容斥原理、矩阵快速幂、乘法逆元、生成函数、FFT快速傅里叶变换等进行考察。
四道相关推荐题(课后作业):
-
[NOI2010] 能量采集
-
[清华集训2012] 模积和
-
[LMXOI Round 1] Dreamer
-
[SDOI2017] 遗忘的集合
BiLiBiLi:@芝土密密拉
第一题
[蓝桥杯 2018 国 B] 矩阵求和
第一题式子详细推导过程:
原式:∑i=1n∑j=1ngcd(i,j)2=∑i=1n∑j=1n∑k=1nk2[gcd(i,j)=k]=∑i=1⌊kn⌋∑j=1⌊kn⌋∑k=1nk2[gcd(i,j)=1]=∑k=1nk2∑i=1⌊kn⌋∑j=1⌊kn⌋[gcd(i,j)=1]=∑k=1nk2∑i=1⌊kn⌋∑j=1⌊kn⌋∑d∣gcd(i,j)⌊kn⌋μ(d)=∑k=1nk2∑i=1⌊kn⌋∑j=1⌊kn⌋∑d=1⌊kn⌋μ(d)[d∣i][d∣j]=∑k=1nk2∑d=1⌊kn⌋μ(d)∑i=1⌊kn⌋[d∣i]∑j=1⌊kn⌋[d∣j]=∑k=1nk2∑d=1⌊kn⌋μ(d)⌊kdn⌋⌊kdn⌋
第一题思路:
原式:∑i=1n∑j=1ngcd(i,j)2最终式:∑k=1nk2∑d=1⌊kn⌋μ(d)⌊kdn⌋⌊kdn⌋令F(n)=∑d=1nμ(d)⌊dn⌋⌊dn⌋对F(n),易分块处理。问题即转化为∑k=1nk2F(kn)。
第一题C++程序代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(x,y,z) for(int x=y;x<=z;x++)
const int N=1e7+5,mod=1e9+7;
int primes[N],pj,mu[N],n,p[N];
bool st[N];
void init(){
int n=N-1;
mu[1]=1;
rep(i,2,n){
if(!st[i]){
primes[++pj]=i;
mu[i]=-1;
}
for(int j=1;i*primes[j]<=n;j++){
int m=i*primes[j];
st[m]=1;
if(i%primes[j]==0){
mu[m]=0;
break;
}else mu[m]=-mu[i];
}
}
rep(i,1,n){
mu[i]+=mu[i-1];
p[i]=(p[i-1]+1LL*i*i%mod)%mod;
}
}
int F(int x){
int res=0;
for(int l=1,r;l<=x;l=r+1){
r=x/(x/l);
res=(res+1LL*(mu[r]-mu[l-1])*(x/l)*(x/l)%mod)%mod;
}
return res;
}
int calc(){
int res=0;
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
res=(res+(p[r]-p[l-1]+mod)%mod*1LL*F(n/l)%mod)%mod;
}
return res;
}
int main(){
init();
cin>>n;
cout<<calc();
return 0;
}
第二题
[国家集训队] Crash的数字表格
第二题式子详细推导过程:
设n<m。原式=∑i=1n∑j=1mlcm(i,j)=∑i=1n∑j=1mgcd(i,j)ij=∑i=1n∑j=1m∑k=1nkij [gcd(i,j)=k]=∑i=1⌊kn⌋∑j=1⌊km⌋∑k=1nk2kij [gcd(i,j)=1]=∑k=1n∑i=1⌊kn⌋∑j=1⌊km⌋kij [gcd(i,j)=1]=∑k=1nk∑i=1⌊kn⌋∑j=1⌊km⌋ij∑d∣gcd(i,j)⌊kn⌋μ(d)=∑k=1nk∑i=1⌊kn⌋∑j=1⌊km⌋ij∑d=1⌊kn⌋μ(d)[d∣i][d∣j]=∑k=1nk∑i=1⌊kn⌋i[d∣i]∑j=1⌊km⌋j[d∣j]∑d=1⌊kn⌋μ(d)=∑k=1nk∑i=1⌊kdn⌋id∑j=1⌊kdm⌋jd∑d=1⌊kn⌋μ(d)=∑k=1nk∑d=1⌊kn⌋μ(d)d2∑i=1⌊kdn⌋i∑j=1⌊kdm⌋j
第二题思路:
原式:∑i=1n∑j=1mlcm(i,j)最终式:∑k=1nk∑d=1⌊kn⌋μ(d)d2∑i=1⌊kdn⌋i∑j=1⌊kdm⌋j令F(n,m)=∑d=1nμ(d)d2∑i=1⌊dn⌋i∑j=1⌊dm⌋j令G(n,m)=∑i=1ni∑j=1mj问题即转化为∑k=1nkF(n,m),F(n,m)=∑d=1nμ(d)d2G(n,m)。
第二题C++程序代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(x,y,z) for(int x=y;x<=z;x++)
const int N=1e7+5,mod=20101009;
int n,m,primes[N],pj,mu[N],s[N];
bool st[N];
void init(){
int n=N-1;
mu[1]=1;
rep(i,2,n){
if(!st[i]){
primes[++pj]=i;
mu[i]=-1;
}
for(int j=1;i*primes[j]<=n;j++){
int m=i*primes[j];
st[m]=1;
if(i%primes[j]==0){
mu[m]=0;
break;
}else mu[m]=-mu[i];
}
}
rep(i,1,n) s[i]=((s[i-1]+1ll*mu[i]*i*i)%mod+mod)%mod;
}
int G(int n,int m){
return (1ll*n*(n+1)/2%mod)*(1ll*m*(m+1)/2%mod)%mod;
}
int F(int n,int m){
int res=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
res=(res+1ll*(s[r]-s[l-1])%mod*G(n/l,m/l)%mod+mod)%mod;
}
return res;
}
int calc(){
if(n>m) swap(n,m);
int res=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
res=(res+1ll*(r-l+1)*(l+r)/2%mod*F(n/l,m/l)%mod)%mod;
}
return res;
}
int main(){
init();
cin>>n>>m;
cout<<calc();
return 0;
}
共有 0 条评论