莫比乌斯反演
莫比乌斯函数
莫比乌斯反演
若 ,则
证明:
一般使用式子
若 证明:
常用卷积关系
常见积性函数
- 单位函数
- 幂函数
- 因数个数
- 欧拉函数
常见公式
常见结论
P2522 [HAOI2011] Problem b
题意:
给出a,b,c,d,k,求
思路:
定义
令
- 然后求的话就是二维前缀和容斥
- 算的时候用整除分块,枚举每个公共的块,使得
- 复杂度为
P1829 [国家集训队] Crash的数字表格 / JZPTAB
题意:
求
思路:
定义
分块套分块解决,复杂度为
cpp
int n,m;
int mu[N],sum[N];
bool vis[N];
vector<int> prime;
void sieve(){
mu[1]=1;
for(int i=2;i<N;i++){
if(!vis[i]){
vis[i]=1;
prime.push_back(i);
mu[i]=-1;
}
for(int j=0;j<prime.size()&&prime[j]*i<N;j++){
vis[prime[j]*i]=1;
if(i%prime[j]==0)break;
mu[prime[j]*i]=-mu[i];
}
}
for(int i=1;i<N;i++)sum[i]=(sum[i-1]+mu[i]*i%mod*i%mod)%mod,sum[i]=(sum[i]+mod)%mod;
}
int G(int n,int m){
return n*(n+1)/2%mod*(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+((sum[r]-sum[l-1])%mod+mod)%mod*G(n/l,m/l)%mod)%mod;
}
return res;
}
int cal(int n,int m){
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+(r-l+1)*(l+r)/2%mod*F(n/l,m/l)%mod)%mod;
}
return res;
}
void solve(){
int n,m;
cin>>n>>m;
sieve();
cout<<cal(n,m)<<"\n";
}P3704 [SDOI2017] 数字表格
题意:
求
思路:
cpp
bool vis[N];
int mu[N],F[N],f[N],invf[N];
vector<int> prime;
int qpow(int a,int b){
int ans=1;
for(;b;b>>=1){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
}
return ans;
}
void init(){
mu[1]=1;
f[1]=F[0]=F[1]=invf[0]=invf[1]=1;
for(int i=2;i<N;i++){
if(!vis[i]){
prime.push_back(i);
mu[i]=-1;
}
for(int j=0;j<prime.size()&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
mu[i*prime[j]]=-mu[i];
}
f[i]=(f[i-1]+f[i-2])%mod;
invf[i]=qpow(f[i],mod-2);
F[i]=1;
}
for(int i=1;i<N;i++){
for(int j=i;j<N;j+=i){
if(mu[j/i])F[j]=(F[j]*(mu[j/i]==1?f[i]:invf[i]))%mod;
}
}
for(int i=2;i<N;i++)F[i]=F[i]*F[i-1]%mod;
}
int cal(int n,int m){
if(n>m)swap(n,m);
int ans=1;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
int s=F[r]*qpow(F[l-1],mod-2)%mod;
ans=ans*qpow(s,(n/l)*(m/l))%mod;
}
return ans;
}
void solve(){
int n,m;
cin>>n>>m;
cout<<cal(n,m)<<"\n";
}P3327 [SDOI2015] 约数个数和
题意:
思路:
带入原式得,
cpp
bool vis[N];
int mu[N],d[N],t[N];//t为最小质因子出现次数
vector<int> prime;
void init(){
mu[1]=d[1]=1;
for(int i=2;i<N;i++){
if(!vis[i]){
vis[i]=1;
prime.push_back(i);
mu[i]=-1;
d[i]=2;
t[i]=1;
}
for(int j=0;j<prime.size()&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0){
d[i*prime[j]]=d[i]/(t[i]+1)*(t[i]+2);
t[i*prime[j]]=t[i]+1;
break;
}
mu[i*prime[j]]=-mu[i];
d[i*prime[j]]=d[i]*2;
t[i*prime[j]]=1;
}
}
for(int i=2;i<N;i++){
d[i]+=d[i-1],mu[i]+=mu[i-1];
}
}
int cal(int n,int m){
if(n>m)swap(n,m);
int ans=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(mu[r]-mu[l-1])*d[n/l]*d[m/l];
}
return ans;
}
void solve(){
int n,m;
cin>>n>>m;
cout<<cal(n,m)<<"\n";
}