演算法隨筆——數論之莫比烏斯反演

codwarm發表於2024-06-01

連結
連結2
連結3
連結4

前置知識:

數論分塊

可以求形如:\(\sum f(i)g(\left \lfloor n/i \right \rfloor )\) 的東西。
原理如下:
比如說求 $\sum_{i=1}^{10}\left \lfloor 10/i \right \rfloor $
得到:10 5 3 2 2 1 1 1 1 1
可以發現有一些塊的數值是一樣的。
具體一點可以發現 \([l, \left \lfloor \frac{n}{\left \lfloor \frac{n}{l} \right \rfloor } \right \rfloor ]\) 裡的數值都是一樣的。
又因為這樣的值只有 \(\sqrt n\) 個,因此這個式子可以在 \(O(\sqrt n)\) 的複雜度算出來.

int sum(int n)
{
	int res = 0;
	for (int i = 1,r;i <= n;i = r + 1)
	{
		r = n/(n/i);
		res += ...//計算貢獻
	}
	return res;
}

狄利克雷卷積

一些數論函式:
\(\epsilon (n)\) : \([n=1]\)
\(I(n)\):任何情況下,\(I(n) = 1\)
\(id(n)\): \(id(n) = n\)
\(\varphi(n)\) : 尤拉函式, \([1,n]\) 之內與 \(n\) 互質的整數的個數.單點求解尤拉函式

點選檢視程式碼
int get_euler(int n)
{
    phi[1] = 1;
    for (int i = 2;i <= n;i++)
    {
        if (!vis[i]) 
        {
            prime[cnt++] = i;
            phi[i] = i - 1; 
        }
        for (int j = 0;prime[j]<= n/i;j++)
        {
            vis[prime[j] * i] = 1;
            if (i % prime[j] == 0)
            {
                phi[i*prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[prime[j] * i] = phi[i] * (prime[j]-1);
        }
    }
    return res;
}

莫比烏斯函式 \(\mu\)
image
篩法:

點選檢視程式碼
void euler(int n)
{
	mu[1] = 1;
	for (int i = 2;i <= n;i++)
	{
		if (!vis[i]) primes[cnt++] = i,mu[i] = -1;
	 	for (int j = 0;primes[j] <= n / i;j++)
	 	{
	 		int num = i * primes[j];
	 		vis[num] = 1;
	 		if (i % primes[j] == 0)
	 		{
	 			mu[num] = 0;
	 			break;
	 		}
	 		mu[num] = -mu[i];
	 	}		
	}
}

\(\sigma(n)\) 約數和函式:\(\sigma(n) = \sum _{d|n} d\)

狄利克雷卷積

\[{\large (f*g)(n) = \sum_{d|n}^{} f(d) \times g(\frac{n}{d})} \]

則有:

\[{\large \mu * I = \epsilon} \]

\[{\large \varphi * I = id} \]

\[{\large \mu * id = \varphi} \]

\[{\large f * \epsilon = f} \]

\[{\large I * id = \sigma} \]

\(\epsilon\) 是單位函式,\(\mu\)\(I\) 互為逆元。
同時可以發現狄利克雷卷積滿足交換律、分配律和結合律。

例題1

${\large \mu * I = \epsilon} $

image
image

例題2

${\large \varphi * I = id} $

image

例題3

${\large \mu * I = \epsilon} $

image

相關文章