1. 程式人生 > >莫比烏斯反演

莫比烏斯反演

isp init 我們 線性 spa 線性篩 之前 element int

莫比烏斯反演在許多情況下可以簡化運算。

定理:F(n)和f(n)是定義在非負整數集合上的兩個函數,並且滿足條件F(n)=∑d|n f(d)。

附:∑d|n 的意思是對所有n的因子d求和。

那麽,我們得到結論:

    f(n)=∑d|n μ(d)F(n/d)

在上面的公式中有一個μ(d)函數(莫比烏斯函數),它的定義如下:

(1) 若d==1,那麽μ(d)=1;

(2) 若d=p1p2p3...pk,pi均為互異素數,那麽μ(d)=(-1)k次方;

(3) 其他情況下μ(d)=0;

對於μ(d)函數,它有如下常見性質:

(1) 對任意正整數n有:∑d|n μ(d)= 1 if(n==1) else if(n>1) =0

(2) 對任意正整數n有:∑d|n μ(d)/d = φ(n)/n

用線性篩法求莫比烏斯函數的代碼:

bool vis[10045];//標記數組,是否是素數 
int n,cnt,prime[10045],mu[10045];//n是範圍,cnt是素數個數,prime是素數數組,mu是該數的莫比烏斯函數 
void init()
{
    mu[1]=1;//1的莫比烏斯函數是1 
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])//如果是素數 
        {
            mu[i]=-1;//k=1,所以該數的莫比烏斯函數是-1 
            prime[++cnt]=i;//
記錄素數 } for(int j=1;j<=cnt&&i*prime[j]<=n;j++)//遍歷之前的素數,並且i*prime[j]在n的範圍內 { vis[i*prime[j]]=1;//合數 if(i%prime[j])//如果i是素數 mu[i*prime[j]]=-mu[i];//k+1,所以莫比烏斯函數取相反數 else { mu[i*prime[j]]=0;//其他情況莫比烏斯函數為0
break; } } } }

接下來是莫比烏斯反演定理的證明:

恒等變形得:

f(n)=d|nμ(d)F(nd)=d|nμ(d)k|ndf(k)=k|nf(k)d|nkμ(d)

因為之前證明的這個定理:

d|nμ(d)={10n==1n>1

所以當且僅當nk=1,即n=k時,d|nkμ(d)=1,其余時候等於0。

k|nf(k)d|nkμ(d)=f(n)

莫比烏斯反演