Dirichlet Convolution

Dirichlet Convolution

符号及规定

  • \([\text{condition}]\) 表示当 \(\text{conditon}\) 为真时,\([\text{condition}]=1\),否则为 \(0\)
  • \(\textbf{1}(n)=1\) 常数函数,永远等于 \(1\)
  • \(\varepsilon(n)=[n=1]\) 单位函数
  • \(\text{Id}(n)=n\) 恒等函数
  • \(\text{Id}_k(n)=n^k\) 幂函数
  • \(d(n)\) 约数个数函数
  • $\sigma(n) $ 约数和函数
  • \(\sigma_k(n)\) 除数函数,表示 \(n\) 所有因数 \(k\) 次方的和。

数论函数

\(f,g\) 两个函数是数论函数。

加法:两个函数直接相加 \((f+g)(x)=f(x)+g(x)\)

数乘(一个数乘到一个数论函数上):这个数和函数中的每一项都相乘, \((xf)(n)=x·f(n)\)

狄利克雷卷积

\(f,g\) 是数论函数,若数论函数 \(h\) 满足:

\[h(n)=\sum_{d\mid n}f(d)g\left(\frac{n}{d}\right) \]

当然也可写作:

\[h(n)=\sum_{ij=n}f(i)g(j) \]

则称 \(h\)\(f\)\(g\) 的狄利克雷卷积,记作: \(h=f*g\)

例子: \(h(6)=f(1)g(6)+f(2)g(3)+f(3)g(2)+f(6)g(1)\)

性质

  • 交换律 \(f*g=g*f\)。这个是显然的。
  • 结合律 \((f*g)*h=f*(g*h)\)

原因:

\[\sum_{(i\cdot j)\cdot k=n}(f(i)g(j))h(k)=\sum_{i\cdot( j\cdot k)=n}f(i)(g(j)h(k)) \]

于是我们可以把 \(f*(g*h)\) 写作 \(f*g*h\)

  • 分配律 \((f+g)*h=f*h+g*h\)。这个也是显然的。

  • 没有名字律 \((xf)*g=x(f*g)\)。显然。

  • 单位函数 \(\epsilon\) 是狄利克雷卷积的单位元,即对于任意数论函数 \(f\) 都有 \(\varepsilon*f=f*\varepsilon=f\)

  • 类比数论倒数(乘法逆元)的思路,对于每个 \(f(1)\not=0\) 的数论函数 \(f\),都存在一个函数 \(g\) 使得 \(f*g=\varepsilon\)

我们来重点考虑一下这个逆元,专业一点的话不妨称之为 狄利克雷逆元

定义

\[g(n)=\frac{1}{f(1)}\left(\varepsilon(n)-\sum_{i \mid n,i\not=1}f(i)g\left(\frac{n}{i}\right) \right) \]

这样

\[\begin{split}(g*f)(n)&=\sum\limits_{i\mid n} f(i)g(\frac{n}{i})\\&=f(1)g(n)+\sum\limits_{i\mid n,i\not= 1}f(i)g(\frac{n}{i})\\&=\varepsilon(n)\end{split} \]

积性函数

若一个数论函数 \(f\) 满足:当 \(\gcd(n,m)=1\) 时, \(f(nm)=f(n)\cdot f(m)\),则称其为积性函数。

一些常见的积性函数:

  • \(\varepsilon(n)=[n=1]\)
  • \(\text{Id}(n)=n\)
  • \(\text{Id}_k(n)=n^k\)
  • \(\textbf{1}(n)=1\)

\(\uparrow\) 完全积性函数,无论 \(n,m\) 是否互质,都满足 \(f(nm)=f(n)f(m)\)

\(\downarrow\) 积性函数

  • \(d(n)\)

\(nm\) 的每个约数 \(t\) 都可以被分解成一个 \(n\) 的约数 \(\gcd(t,n)\) 以及 \(m\) 的约数 \(\gcd(t,m)\) 之积,且一一对应。比较显然吧

  • \(\varphi(n)\)

$\gcd(t,nm)=1\Leftrightarrow \gcd(t,n),\gcd(t,m)\Leftrightarrow \gcd((t \bmod n),n),\gcd((t\bmod m),m) $ 这意味着每一个 \([1,nm]\) 中的 \(t\) 都可以在 \([1,n]\)\([1,m]\) 中找到与 \(n,m\) 互质的 \(t\bmod n,t\bmod m\)

由中国剩余定理可知 \(\gcd(n,m)=1\) 时,\(t\equiv a\pmod n,t\equiv b\pmod m\) 的最小解为 \(t_0 \bmod {nm}\),故在 \([1,mn]\) 内仅有一个 \(t\)。所以得证。

接下来证明一个很重要的结论,两个积性函数的狄利克雷卷积是积性函数

首先有一个性质:若 \(\gcd(n,m)=1,a\mid n,b\mid m\),则 \(\gcd(a,b)=1\)。这是很显然的。

\[\begin{split}(g*f)(nm)&=\sum\limits_{d\mid nm} f(d)g\left(\frac{mn}{d}\right)\\&=\sum\limits_{a\mid n,b\mid m}f(a)f(b)g\left(\frac{n}{a}\right)g\left(\frac{m}{b}\right)\\&= \left(\sum\limits _{a\mid n}f(a)g\left(\frac n a\right)\sum\limits _{b\mid m}f(b)g\left(\frac m b\right)\right)\\&=(g*f)(n)(g*f)(m)\end{split} \]

我们再证一个很重要的结论,积性函数 \(f\) 的狄利克雷逆元 \(g\) 是积性函数

\[g(n)=\frac{1}{f(1)}\left(\varepsilon(n)-\sum_{i \mid n,i\not=1}f(i)g\left(\frac{n}{i}\right) \right) \]

考虑数学归纳法。对 \(nm\) 的大小进行归纳。

  1. \(nm=1\) 时,\(g(1)=1\),结论成立。

  2. 假设 \(nm>1\) 时,对于 \(n'm'<nm\)\(g(n'm')=g(n')g(m')\)

\[\large\begin{split}g(nm)&=-\sum\limits_{d\mid nm,d\not =1}f(d)g\left(\frac{nm}{d}\right)\\&=-\sum\limits_{a\mid n,b\mid m,ab\not =1}f(ab)g\left(\frac{nm}{ab}\right)\\&=\color{\pink}{-\sum\limits_{a\mid n,b\mid m,ab\not =1} f(a)(b)g\left(\frac{n}{a}\right)g\left(\frac m b\right)}\\&=f(1)f(1)g(n)g(m)-\sum\limits_{a\mid n,b\mid m}f(a)(b)g\left(\frac n a\right)g\left(\frac m b\right)\\&=g(n)g(m)-\left(\sum\limits_{a\mid n}f(a)g\left(\frac n a\right)\right)\left(\sum\limits_{b\mid m}f(b)g\left(\frac m b\right)\right)\\&=g(n)g(m)-\varepsilon(n)\varepsilon(m)=g(n)g(m)\end{split} \]

有一些要注意的:

  • \(f(1)=1\),因为 \(f(1)=f(1)f(1)\)
  • 粉色部分运用了归纳条件,\(\dfrac{nm}{ab}<nm\)

为什么说这个结论很重要呢?

因为积性函数可以线性筛出来。

线性筛

\(O(n)\) 的时间内筛出某个东西。

线性筛素数

保证每个数只被最小质因子筛掉。

因为我太逊了,所以代码都是蒯的。

int pri[N],tot,zhi[N];//zhi[i]为1的表示不是质数
void sieve()
{
    zhi[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!zhi[i]) pri[++tot]=i;
        for (int j=1;j<=tot&&i*pri[j]<=n;j++)
        {
            zhi[i*pri[j]]=1;
            if (i%pri[j]==0) break;
        }
    }
}

个人习惯把 zhi 写成 bitset 的。

线性筛莫比乌斯函数

\(\mu(1)=1\)\(i\) 为质数时 \(\mu(i)=-1\)。最小质因子筛到的时候比 \(i\) 多了一个质数所以反过来。

	isprime[1] = 1; mu[1] = 1;
	for(int i = 2; i < N; ++i){
		if(!isprime[i]){  prime[++num] = i; mu[i] = -1;  }
		for(int j = 1; j <= num && i * prime[j] < N; ++j){
			isprime[i * prime[j]] = 1;
			if(i % prime[j]) mu[i * prime[j]] = -mu[i];
			else{  mu[i * prime[j]] = 0; break;  }
		}
	}

线性筛欧拉函数

\(p \mid n\)\(n\) 含有 \(np\) 所有的质因子,所以 \(\varphi(np)=p\times n\prod \limits _{i=1}^{k} (1-\dfrac{1}{p_i})=p \times \varphi(n)\)

\(p\nmid n\)\(\varphi(np)=\varphi(p) \times \varphi(n)=(p-1)\times \varphi(n)\) .

bitset<2333> used;
int p[233],cnt;
long long phi[2333];
inline void getphi()
{
    phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!used[i])
            p[++cnt]=i,phi[i]=i-1;
        for(int j=1;j<=cnt&&i*p[j]<=n;j++)
        {
            int val=i*p[j];
            used[val]=1;
            phi[val]=phi[i]*(i%p[j]?p[j]-1:p[j]);
            if(i%p[j]==0)   break;
        }
    }
}

线性筛约数个数

\(n=\prod \limits_{i=1}^k p_i^{a_i}\)\(d(n)=\prod\limits_{i=1}^k(a_i+1)\)。这个十分的显然,乘法原理。

只要记录每个数最小质因数的指数即可。

int d[N],a[N],pri[N],tot,zhi[N];
void sieve()
{
    zhi[1]=d[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!zhi[i]) pri[++tot]=i,d[i]=2,a[i]=1;
        for (int j=1;j<=tot&&i*pri[j]<=n;j++)
        {
            zhi[i*pri[j]]=1;
            if (i%pri[j]) d[i*pri[j]]=d[i]*d[pri[j]],a[i*pri[j]]=1;
            else {d[i*pri[j]]=d[i]/(a[i]+1)*(a[i]+2);a[i*pri[j]]=a[i]+1;break;}
        }
    }
}

线性筛约数和

\(n=\prod \limits_{i=1}^k p_i^{a_i}\)\(\sigma(n)=\prod\limits_{i=1}^{k}\left(\sum\limits_{j=1}^{a_i}p_i^j\right)\)。这个也是,把 \(\prod\)\(\sum\) 去掉写成一大堆括号就很显然了。

维护两个东西:

  • \(low_i\) 表示 \(i\) 的最小质因子的指数次幂,即 \(p_1^{a_1}\)
  • \(sum_i\) 表示 \(i\) 的最小质因子对答案的贡献,即 \(\sum\limits_{j=1}^{a_1}p_1^j\)
int low[N],sum[N],sigma[N],pri[N],tot,zhi[N];
void sieve()
{
    zhi[1]=low[1]=sum[1]=sigma[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!zhi[i]) low[i]=pri[++tot]=i,sum[i]=sigma[i]=i+1;
        for (int j=1;j<=tot&&i*pri[j]<=n;j++)
        {
            zhi[i*pri[j]]=1;
            if (i%pri[j]==0) 
            {
                low[i*pri[j]]=low[i]*pri[j];
                sum[i*pri[j]]=sum[i]+low[i*pri[j]];
                sigma[i*pri[j]]=sigma[i]/sum[i]*sum[i*pri[j]];
                break;
            }
            low[i*pri[j]]=pri[j];
            sum[i*pri[j]]=pri[j]+1;
            sigma[i*pri[j]]=sigma[i]*sigma[pri[j]];
        }
    }
}

线性筛其他积性函数

要线性筛出积性函数 \(f(x)\),就必须快速计算出以下函数值:

  • \(f(1)\)
  • \(f(p)\)
  • \(f(p^k)\)

其中 \(p \in \text{Prime}\)

我们考虑筛的过程有\(i\times pri_j\) 这样一个数。

\(i\) 惟一分解得到 \(p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k}\),则 \(pri_j\le p_1\)。这是显然的,结合线性筛的流程,当 \(pri_j=p_1\) 时就 break 了。

\(pri_j < p_1\) 时,\(f(x)=f(i)f(pri_j)\)

\(pri_j=p_1\) 时,\(\gcd\left(\dfrac{i}{low_i},low_i\times pri_j\right)=1\)\(f(x)=f\left(\dfrac{i}{low_i}\right)f\left(low_i\times pri_j\right)\)

注意,当 \(low_i=i\) 时, \(i=p^k\),需要特殊定义,直接计算。

void sieve()
{
    zhi[1]=low[1]=1;
    f[1]=对1直接定义;
    for (ll i=2;i<=n;i++)
    {
        if (!zhi[i]) low[i]=pri[++tot]=i,f[i]=对质数直接定义;
        for (ll j=1;j<=tot&&i*pri[j]<=n;j++)
        {
            zhi[i*pri[j]]=1;
            if (i%pri[j]==0)
            {
                low[i*pri[j]]=low[i]*pri[j];
                if (low[i]==i)
                    f[i*pri[j]]=对质数的若干次幂进行定义(一般由f[i]递推);
                else
                    f[i*pri[j]]=f[i/low[i]]*f[low[i]*pri[j]];
                break;
            }
            low[i*pri[j]]=pri[j];
            f[i*pri[j]]=f[i]*f[pri[j]];
        }
    }
}

一些常见的卷积

除数函数和幂函数

\[\left(\text{Id}_k(n)*\textbf{1}\right)(n)=\sum_{d\mid n}\text{Id}_k(d)=\sum_{d\mid n}d^k=\sigma_k(n) \]

所以 \(\text{Id}_k* \textbf{1}=\sigma_k\)

此时,我们发现一个很重要的性质,对于任意一个数论函数 \(f\)

\[(f*\textbf{1})(n)=\sum_{d\mid n}f(d) \]

欧拉函数和恒等函数

首先重温一下 \(\varphi(n)=n \prod\limits_{p\mid n}(1-\frac{1}{p}),p\in \text{Prime}\)

我们尝试先从 \(n=p^k\) 考虑。

\[\begin{split}(\varphi(n)*\textbf{1})&=\sum_{d\mid n}\varphi(d)\\&=\varphi(1)+\sum_{i=1}^{k}\varphi(p^i)\\&=1+\sum_{i=1}^k (p^i-p^{i-1})\\&=p^k\\&=n\end{split} \]

于是考虑更普遍的情况,将 \(n\) 分解为 \(p_1^{k_1}\times p_2^{k_2}\times \cdots \times p_m^{k_m}\)。因为 \(\varphi\)\(\textbf{1}\) 均为积性函数,所以 \(\varphi*\textbf{1}\) 也是积性函数。而 \((\varphi*\textbf{1})(p_i^{k_i})=p_i^{k_i}\),所以 \((\varphi*\textbf{1})(n)=n=\text{Id}(n)\)

所以 \(\varphi*\textbf{1}=\text{Id}\)

常数函数和约数个数函数

\[\begin{split}(\textbf{1}*\textbf{1})(n)&=\sum_{d\mid n}\textbf{1}(d)\textbf{1}\left(\frac{n}{d}\right)\\&= \sum _ {d\mid n}1 \\&=d(n) \end{split} \]

其他

我们可以自己发挥,例如:

\[\sigma=\text{Id}* \textbf{1}=\varphi*\textbf{1}*\textbf{1}=\varphi*d \]

莫比乌斯反演

Link.

参考资料

posted @ 2021-08-19 16:10  LJC001151  阅读(38)  评论(0)    收藏  举报