莫比烏斯函數


前言

本文內容大部分來自Oier PoPoQQQ 的課件。\
onedrive, baidu
pan
,密碼:6ug5\

本文基本上由我學習相當於是制作的一篇學習筆記,但是將課件中的一些不完善的地方加以完善
使得更容易理解,加上了部分例題的代碼

引子

介紹莫比烏斯反演之前我們先來看一個函數

根據 的定義

於是我們便可以通過 推導出

在推導的過程中我們是否發現了一些規律?

莫比烏斯反演

莫比烏斯反演[1]

莫比烏斯反演定義

其中 為莫比烏斯函數[1],定義如下

莫比烏斯函數的定義式[2]

莫比烏斯函數的性質

(1)

當n不等於1時,n所有因子的莫比烏斯函數值的和為0,\

那么

證明:

(2)

對於 有:

(3)

積性函數 數論上積性函數的定義\

積性函數的性質\

\

積性函數的前綴和也是積性函數\
\

因為積性函數是積性函數,

因此可以通過線性篩求出莫比烏斯函數的值

mu[1]=1;
for(i=2;i<=n;i++){
    if(!not_prime[i]){
        prime[++tot]=i;
        mu[i]=-1;
    }
    for(j=1;prime[j]*i<=n;j++){
        not_prime[prime[j]*i]=1;
        if(i%prime[j]==0){
            mu[prime[j]*i]=0;
            break;
        }
        mu[prime[j]*i]=-mu[i];
    }
}

例題1:

BZOJ 2440
完全平方數
\

題目大意:求第k個無平方因子數[3]\

做法:
首先二分答案,問題轉化為求 之間有多少個無平方因子數\
根據容斥原理可知,對於 之內所有的質數,
答案G(x)=0個質數平方倍數的個數-1個質數平方倍數的個數+2個質數平方倍數的個數-...,
那么對於偶數個質數平方對於答案的貢獻就是正的,否則是負的,\
如果不是若干個互異質數的乘積,那么對答案沒有影響,

如何表示這個式子呢?\

觀察莫比烏斯函數的定義[1],可以知道對於能對答案產生貢獻的數 ,其中 分解得到質數的個數
根據上述說明,那么可以得知結果\

#include<iostream>
#include<cstdio>
#include<cmath>
#define N 100005
using namespace std;

bool not_prime[N];
int prime[N];
int mu[N];
int tot;

void Mu(int n){
int i,j;
mu[1]=1;
for(i=2;i<=n;i++){
if(!not_prime[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(j=1;prime[j]i<=n;j++){
not_prime[prime[j]
i]=1;
if(i%prime[j]==0){
mu[prime[j]i]=0;
break;
}
mu[prime[j]
i]=-mu[i];
}
}
}
int can(int x){
int sum=0;
int s=floor(sqrt(x));
for(int i=1;i<=s;++i)
if(mu[i])
sum+=mu[i]floor(x/(ii));
return sum;
}

int main(){
Mu(N);int T,sum;
scanf("%d",&T);
while(T--){
scanf("%d",&num);
long long l=1,r=num<<1,mid;
while(l<r){
mid=(l+r)>>1;
if(can(mid)<num)
l=mid+1;
else r=mid;
}
printf("%lld\n",r);
}
return 0;
}

莫比烏斯反演定理的證明

證明:

形式二:

證明同理,一般要用到的都是這種形式

莫比烏斯反演的應用

對於一些函數 ,如果我們很難直接求出它的值,而容易求出倍數和或約數和 ,

那么我們可以直接利用莫比烏斯反演來求得 的值

例:

f(n)表示某一范圍內(x,y)=n的數對的數量,\

F(n)表示某一范圍內n|(x,y)的數對的數量\

那么直接求f(n)並不是很好求,而F(n)求起來相對無腦一些,\

那么我們可以通過對F(n)進行莫比烏斯 反演來求得f(n)</p>

例題2:

BZOJ 2301 Problem

b

題目大意:詢問有多少對 滿足

根據容斥原理,這個題目就可以轉化成

其中答案為 </p>

那么我們需要快速求出

這個式子可以進一步轉化為

考慮莫比烏斯反演, 令

分析可知這個算法的復雜度是

我們還需要對這個算法進行進一步優化

因為 至多只有 個取值,

那么 至多只有 個取值

因為使得 成立的 值都是連續的,

所以可以維護一個莫比烏斯函數的前綴和,

這樣就可以在 的時間內出解

枚舉除法的取值在莫比烏斯反演的應用當中非常常用

if(a>b)swap(a,b);
for(i=1;i<=a;i=last+1){
last=min(a/(a/i),b/(b/i));
re+=(a/i)(a/i)(sum[last]-sum[i-1]);
}
return re;

代碼異常好寫

#include<iostream>

include<cstdio>

include<cmath>

define N 50005

define inf 0x7fffffff

using namespace std;

bool not_prime[N];
int prime[N];
int sum[N];
int mu[N];
int tot;

void Mu(int n){
int i,j;
mu[1]=1;
for(i=2;i<=n;i++){
if(!not_prime[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(j=1;prime[j]i<=n;j++){
not_prime[prime[j]
i]=1;
if(i%prime[j]==0){
mu[prime[j]i]=0;
break;
}
mu[prime[j]
i]=-mu[i];
}
}
for(int i=1;i<=n;++i)
sum[i]=sum[i-1]+mu[i];
}
int ans(int n,int m){
if(n>m)swap(n,m);
int last,i,re=0;
for(i=1;i<=n;i=last+1){
last=min(n/(n/i),m/(m/i));
re+=(n/i)(m/i)(sum[last]-sum[i-1]);
}
return re;
}

int main(){
Mu(N);
int T;
int a,b,c,d,k;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
a--;c--;
a/=k;b/=k;c/=k;d/=k;
int Ans=ans(b,d)-ans(a,d)-ans(b,c)+ans(a,c);
printf("%d\n",Ans);
}
return 0;
}

BZOJ 10s但是luogu卻莫名WA\

全部加上long long 之后總算是過了\

百思不得其解

例題3

BZOJ 2820

YY的GCD
\

題目大意:求有多少數對 滿足 滿足 為質數

做法:


[1] baike:莫比烏斯反演是數論數學中很重要的內容,可以用於解決很多組合數學的問題。

[2]

[3] 無平方因子數(Square-Free

Number),即分解之后所有質因數的次數都為1的數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM