数论函数

参考博客:command_blockANIG

一.定义

0.一些记号

\([S]\) 为 艾弗森括号,定义如下:

\[[S]=\begin{cases}1&S\text{为真}\\0&S\text{为假}\end{cases} \]

1.一些数论函数

\(\varphi(n)=\sum\limits_{i=1}^{n}[\gcd(i,n)=1]\),即 \(n\) 以内与 \(n\) 互质的数的个数,叫做欧拉函数,念做 /fa?/

\(\mu(n)=\begin{cases}1 &n=1\\0 &\exists i\in[1,m],k_i>1 \\(-1)^m & \forall i \in[1,m],k_i=1 \end{cases}\),记 \(n=\prod\limits_{i=1}^{m}p_i^{k_i}\),叫做莫比乌斯函数,念做 /mju:/

下面的表从此博客copy来:

函数名称 符号 定义 积性 卷积
恒等函数 \(I(n)\)\(1(n)\) \(1\) 完全积性函数
元函数 \(\varepsilon(n)\)\(e(n)\) \([n=1]\) 完全积性函数 \(\varepsilon=\mu*1\)
单位函数 \(id(n)\) \(n\) 完全积性函数 \(id=\varphi*1\)
幂函数 \(id^x(n)\) \(n^x\) 完全积性函数
莫比乌斯函数 \(\mu(n)\) 见上 积性函数
欧拉函数 \(\varphi(n)\) 见上 积性函数 \(\varphi=\mu*id\)
约数个数函数 \(d(n)\)\(\sigma_0(n)\) n的约数个数 积性函数 \(d=1*1\)
约数和函数 \(\sigma(n)\) n的约数和 积性函数 \(σ=id*1\)
除数函数 \(\sigma^k(n)\) n的约数k次方和 积性函数 \(σ^k=id^k*1\)

注:\(\varepsilon\) 念做 /'eps?l?n/\(\sigma\) 念做 /'s?ɡm?/

2.积性函数

如果有数论函数 \(f\),满足:

\(\gcd(n,m)=1\),则 \(f(nm)=f(n)f(m)\)

\(f\)积性函数

如果函数 \(g\) 满足:

对于对于任意的 \(n,m\),有 \(g(nm)=g(n)g(m)\)

\(g\)完全积性函数

3.狄利克雷卷积

如果有两个数论函数 \(f\)\(g\),则它们的狄利克雷卷积 \(f*g\) 为:

\[(f*g)(n)=\sum\limits_{d\mid n}f(d)g(\frac{n}{d}) \]

狄利克雷卷积满足:

  • 交换律:\(f*g=g*f\)

  • 结合律:\(f*(g*h)=(f*g)*h\)

  • \(f\)\(g\) 是积性函数,则 \(f*g\) 也是积性函数


二.性质

\(\varphi\) 相关

  • \(p\) 为质数,则 \(\varphi(p)=p-1\).

  • \(p\) 为质数且 \(k\ge1\),则 \(\varphi(p^k)=p^k-p^{k-1}\).

  • \(n=\prod\limits_{i=1}^{m}p_i^{k_i}\),则 \(\varphi(n)=n\times\prod\limits_{i=1}^{m}\frac{p_i-1}{p_i}\).

  • \(p\in\mathbb{P}\),则: \(\varphi(n)=\begin{cases}p\varphi(\frac{n}{p}) &p\mid n\text{ 且 }p^2\nmid n \\(p-1)\varphi(\frac{n}{p}) &p^2\mid n\end{cases}\)

\(\mu\) 相关

  • \(\sum\limits_{d\mid n}\mu(d)=[n=1]\),同理 \([gcd(i,j)=1]=\sum\limits_{d\mid gcd(i,j)}\mu(d)\).

三.算法

1.素数筛子

埃氏筛

很好用的筛子,不过已经线性筛写习惯了,不会写了。

思想很简单,从 \(1\)\(n\) 枚举,如果当前数没被标记,就标记为素数,并把 \(n\) 以内它的倍数标记为合数。

复杂度 \(O(n\log\log n)\)

点击查看代码
ll prime[N],tot;
bool vis[N];
void shai(ll n){
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++tot]=i;
			for(int j=2;i*j<=n;j++){
				vis[i*j]=1;
			}
		}
	}
}

线性筛

神筛子,必须会默写!

思想是只用一个数的最小值质因子筛它,具体见代码实现。

复杂度 \(O(n)\)


线性筛可以筛积性函数,或者一些其他的东西:

我们设 \(p\mid n,p\in\mathbb{P}\),对于本节的所有 \(n\) 成立。

\(\varphi\)

我们知道 \(\varphi\) 满足如下公式:

\[\varphi(n)=\begin{cases}1 & n=1\\p-1 & n=p\\p\cdot \varphi(\frac{n}{p})&p^2\mid n\\(p-1)\cdot \varphi(\frac{n}{p}) & p^2\nmid n\end{cases} \]

于是我们可以在线性筛过程中,发现 \(i\) 为质数时直接计算 \(\varphi(i)\)

\(prime_j\)\(i\times prime_j\) 时,根据是否有 \(prime_j\mid i\) 来计算 \(\varphi(i\times prime_j)\)

\(\mu\)

我们知道 \(\mu\) 满足如下公式:

\[\mu(n)=\begin{cases}1 & n=1\\-1 & n=p\\0 & p^2\mid n\\-\mu(\frac{n}{p}) & p^2\nmid n\end{cases} \]

同样的计算方法。

筛最大质因子

\(mxp(n)\)\(n\) 的最大质因子,且 \(p\)\(n\) 的最小质因子,有:

\[mxp(n)=\begin{cases}p &n=p\\mxp(\frac{n}{p}) &\text{othercases}\end{cases} \]

这样就可以用线性筛筛了。

筛一般积性函数

\(f\) 为积性函数,且 \(f(p^k)\) 可以快速求,于是就可以用线性筛 \(O(n)\) 筛出 \(f\)

具体地,我们设 \(v_i\)\(i\) 的最小质因数,而 \(c_i\) 满足 \(v_i^{c_i}\mid i\;,\;v_i^{c_i+1}\nmid i\),即 \(v_i^{c_i}\)\(i\) 的分解质因数中,属于 \(v_i\) 那一整个幂。

\(c_i\) 满足以下计算式:

\[c_i=\begin{cases}1 & n=p\\c_{\frac{n}{p}}+1&p^2\mid n\\1 & p^2\nmid n\end{cases} \]

我们设 \(g_i=v_i^{c_i}\)\(g_i\) 满足以下计算式:

\[g_i=\begin{cases}p &n=p\\g_{\frac{n}{p}}\cdot p &p^2\mid n\\p & p^2\nmid n\end{cases} \]

于是乎,我们枚举 \(i\in[2,n]\),若 \(i=g_i\),即 \(i=v_i^{c_i}\),可以快速求出 \(f(i)\);否则,有 \(f(i)=f(g_i)\cdot f(\frac{i}{g_i})\),而因为我们按顺序枚举,后两者已经算过了。

下面是封装好的多功能线性筛:

点击查看代码
ll prime[N],v[N],tot;
ll phi[N],mu[N],mxp[N];
ll c[N],g[N],f[N];
void shai(ll n){
	mu[1]=phi[1]=v[1]=mxp[1]=1;
	for(int i=2;i<=n;i++){
		if(!v[i]){
			v[i]=i;prime[++tot]=i;
			phi[i]=i-1;mu[i]=-1;mxp[i]=i;
			c[i]=1;g[i]=i;
		}
		for(int j=1;j<=tot;j++){
			if(prime[j]>v[i]||prime[j]>n/i) break;
			ll x=i*prime[j];
			v[x]=prime[j];
			if(i%prime[j]==0){
				phi[x]=prime[j] * phi[i];mu[x]=0;
				c[x]=c[i]+1;g[x]=g[i]*prime[j];
			}else{
				phi[x]=(prime[j]-1)*phi[i];mu[x]=-mu[i];
				c[x]=1;g[x]=prime[j];
			}
			mxp[x]=mxp[i];
		}
	}
	f[1]=calc(1);
	for(int i=2;i<=n;i++){
		if(i==g[i]) f[i]=calc(i);
		else f[i]=f[g[i]] * f[i/g[i]];
	}
	return;
}

2.前缀和筛子

(一)杜教筛

模板题:P4213 【模板】杜教筛

首先我们证一个东西:

\[\sum\limits_{i=1}^{n} (f*g)(i) = \sum\limits_{i=1}^{n} g(i) \cdot S(\lfloor\frac{n}{i}\rfloor) \]

其中 \(S(n)=\sum\limits_{i=1}^{n}f(i)\)

证明:先把式子左边写出来:

\[\sum\limits_{i=1}^{n} \sum\limits_{d\mid i} g(i)f(\frac{d}{i}) \]

用两个变量 \(i\)\(j\) 来代替 \(d\)\(\frac{d}{i}\),进行循环,则 \(ij\) 就对应原式中的 \(i\),所以有 \(j\le \lfloor\frac{n}{i}\rfloor\)

\[\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{\lfloor\frac{n}{i}\rfloor} g(i)f(j) \]

\(g(i)\) 提出去,剩余的就是 \(f\) 的前缀和:

\[\sum\limits_{i=1}^{n} g(i) \cdot S(\lfloor\frac{n}{i}\rfloor) \]

证毕。

假如我们要求一个函数 \(f\) 的前缀和 \(S\),即 \(S(n)=\sum\limits_{i=1}^{n}f(i)\),其中 \(n\) 很大。

我们可以考虑构造另一个数论函数 \(g\),然后通过刚才证的结论,构造一个 \(S(n)\) 关于 \(S(\lfloor\frac{n}{i}\rfloor)\) 的转移式:

\[\begin{aligned} g(1)S(n)&=\sum\limits_{i=1}^{n} g(i) \cdot S(\lfloor\frac{n}{i}\rfloor) - \sum\limits_{i=2}^{n} g(i) \cdot S(\lfloor\frac{n}{i}\rfloor) \\&= \sum\limits_{i=1}^{n} (f*g)(i) - \sum\limits_{i=2}^{n} g(i) \cdot S(\lfloor\frac{n}{i}\rfloor) \end{aligned}\]

如果 \(g\) 的前缀和可以 \(O(1)\) 算,\(g(i)\) 的单点值也能 \(O(1)\) 算,这个式子就可以在 \(O(n^{\frac{2}{3}})\) 内算出来。

具体地,我们先预处理出 \(k=n^{\frac{2}{3}}\)\(S(1)\sim S(k)\) 的值。

对于某一个询问,前半段直接计算,后半段数论分块,写成记忆化搜索的形式,往前搜索就行了。

一些常见的筛:

1.筛 \(\varphi\)

我们知道 \(\varphi * 1=id\),于是我们取 \(g=1\),有:

\[S_{\varphi}(n)=\sum\limits_{i=1}^{n}(\varphi*1)(i) -\sum\limits_{i=2}^{n}1(i)\cdot S_{\varphi}(\lfloor\frac{n}{i}\rfloor) \]

也就是:

\[\sum\limits_{i=1}^{n}i -\sum\limits_{i=2}^{n}S_{\varphi}(\lfloor\frac{n}{i}\rfloor)=\frac{n(n+1)}{2} -\sum\limits_{i=2}^{n}S_{\varphi}(\lfloor\frac{n}{i}\rfloor) \]

就OK了,直接筛就行。

2.筛 \(\mu\)

我们知道 \(\mu * 1=\varepsilon\),于是我们取 \(g=1\),有:

\[S_{\mu}(n)=\sum\limits_{i=1}^{n}(\mu*1)(i) -\sum\limits_{i=2}^{n}1(i)\cdot S_{\mu}(\lfloor\frac{n}{i}\rfloor) \]

也就是:

\[\sum\limits_{i=1}^{n}\varepsilon(i) -\sum\limits_{i=2}^{n}S_{\mu}(\lfloor\frac{n}{i}\rfloor) = 1-\sum\limits_{i=2}^{n}S_{\mu}(\lfloor\frac{n}{i}\rfloor) \]

min_25筛

单独写一篇博客了,在这里

3.拉格朗日插值

给定 \(n\) 个点对 \((x_1,y_1)\dots(x_n,y_n)\),可以确定一个 \(n-1\) 次的多项式 \(f(x)\),满足 \(\forall i\in[1,n],f(x_i)=y_i\)

\(f(m)\) 的值,或求出 \(f\) 的各项系数。

(一).求值

这部分内容主要来自 此篇博客

我们想办法对于每一对 \((x_k,y_k)\),构造出一个 \(n-1\) 次的函数 \(g_k(x)\),满足:

\[g_k(x)=\begin{cases}y_k & x=x_k\\0 &x= x_i,i\neq k\end{cases} \]

也就是一个专门对付第 \(k\) 个点值的函数,对其他点值无影响。

我们令 \(f(x)=\sum\limits_{k=1}^{n}g_k(x)\),就能够符合题目要求了。

我们先构造出一个满足后半部分的函数:

\[t_k(x)=\prod_{j=1}^{n}[j\neq k](x-x_j) \]

容易验证,当 \(x= x_i,i\neq k\) 时,\(t_k(x)=0\)

如何构造出一个满足全部条件的 \(g_k(x)\) 呢?我们会发现:

\[\frac{t_k(x)}{t_k(x_k)}=\frac{\prod_{j=1}^{n}[j\neq k](x-x_j)}{\prod_{j=1}^{n}[j\neq k](x_k-x_j)} \]

这个函数,满足当\(x= x_i,i\neq k\) 时为 \(0\),而当 \(x=x_k\) 时,分子分母相等,故式子等于 \(1\)

这还不够!我们要求 \(x=x_k\) 时式子值为 \(y_k\)

那我们把 \(y_k\) 乘上去不就行了……

于是我们这样构造出 \(g_k(x)\)

\[g_k(x)=y_k\cdot\frac{t_k(x)}{t_k(x_k)}=y_k\prod_{j=1,j\neq k}^{n}\frac{x-x_j}{x_k-x_j} \]

所以 \(f(x)\) 终于可以表示出来了!

\[f(x)=\sum\limits_{k=1}^{n}y_k\prod_{j=1,j\neq k}^{n}\frac{x-x_j}{x_k-x_j} \]

稍微把变量名微调,然后把 \(x=m\) 带进去,我们就有了拉格朗日插值的最终式子:

\[f(m)=\sum\limits_{i=1}^{n}y_i\prod_{j=1,j\neq i}^{n}\frac{m-x_j}{x_i-x_j} \]

于是乎,我们就能 \(O(n^2)\) 求点值了,当然通过一些预处理和优化,能做到 \(O(n)\)

(二).计算系数

这部分内容主要来自这篇博客

对于一个多项式 \(f(x)\),我们记

\[[x^k]f \]

\(f\)\(x^k\) 项系数。(这里是[]中括号,不知道为什么渲染成了上取整……)

我们提出拉插式子中的系数:

\[a_i=\frac{y_i}{\prod\limits_{j=1,j\neq i}^{n}(x_i-x_j)} \]

可以 \(O(n^2)\) 预处理出 \(a\) 数组:

for(int i=0;i<n;i++){
	a[i]=1;
	for(int j=0;j<n;j++){
		if(i==j) continue;
		(a[i] *= (x[i]-x[j])%mod )%=mod;
	}a[i] = qpow(a[i],mod-2) * y[i]%mod;
}//求a

接下来,我们求一个多项式

\[g(m)=\prod\limits_{j=1}^{n}(m-x_j) \]

的各项系数,这个可以 \(O(n^2)\) 求:

g[0]=1;//最初,是个0次的多项式 "1" 
for(int i=0;i<n;i++){//给它乘上一个 (m-x[i]) 
	for(int j=i+1;j>=1;j--){
		g[j] = ( g[j-1] - g[j] * x[i]%mod ) %mod;
	}g[0]= g[0] * (-x[i])%mod;
}//求g

这时候,原拉插式子就变成了:

\[f(m)=\sum\limits_{i=1}^{n}a_i\frac{g(m)}{m-x_i} \]

我们设\(h(m)=\dfrac{g(m)}{m-c}\),尝试求出 \(h\) 的各项系数:

我们有 \((m-c)h(m)=g(m)\),两边系数对应,有:

\[[m^{k-1}]h-c\cdot[m^k]h=[m^k]g \]

\[[m^k]h=\frac{[m^k]g-[m^{k-1}]h}{-c} \]

于是就可以递推算出来:

for(int i=0;i<n;i++){
	ll inv=qpow(-x[i],mod-2);
	if(!inv){//x[i]=0
		for(int j=0;j<n;j++) h[j]=g[j+1];
	}else{
		h[0]=g[0] * inv%mod;
		for(int j=1;j<n;j++){
			h[j] = (g[j] - h[j-1])%mod *inv%mod;
		}
	}
		for(int j=0;j<n;j++){
		(f[j] += a[i] * h[j]%mod) %=mod; 
	}
}

我们理一理:

  • \(a\)\(n\) 项;
  • \(g\)\(n\) 次的,故有 \(n+1\) 项;
  • \(h\)\(n-1\) 次的,故有 \(n\) 项;
  • \(f\)\(n-1\) 次的,故有 \(n\) 项。

总时间复杂度 \(O(n^2)\)

4.自然数幂和

求:

\[\sum\limits_{i=1}^{n}i^k \]

分为两种情况讨论:

(一). n 小 k 大

因为 \(i^k\) 是完全积性函数,所以可以线性筛筛出来。

\(n\) 以内素数个数为 \(p\),筛出来的复杂度就是 \(p\log k\)

因为 \(n\) 很小,所以直接算前缀和就行了。

(二). n 大 k 小

我们观察 \(k=0,1,2,3\) 的公式:

\[\begin{aligned}&\sum\limits_{i=1}^{n}i^0=n\\&\sum\limits_{i=1}^{n}i^1=\frac{n(n+1)}{2}\\ &\sum\limits_{i=1}^{n}i^2=\frac{n(n+1)(2n+1)}{6}\end{aligned} \]

于是我们发现:当指数为 \(k\) 时,求和公式是一个 \(k+1\) 次的多项式。

cy言:这是积分积出来的,所以多一次。「积分多一次,求导少一次」

所以我们如果想确定指数为 \(k\) 时的通项公式,需要 \(k+2\) 个点值。

于是乎,我们拉格朗日插值插出来。

我们记 \(f(n)=\sum\limits_{i=1}^{n}i^k=\sum\limits_{i=0}^{k+1}f_ix^i\),取 \(k+2\) 个点值 \((x_1,y_1),(x_2,y_2)\dots(x_{k+2},y_{k+2})\)

为了好算,我们取 \(x_i=i\),有:

\[f(n)=\sum\limits_{i=1}^{k+2}y_i\prod_{j=1,j\neq i}^{k+2}\frac{n-j}{i-j} \]

这里面 \(y\) 的求值可以用线性筛做到 \(O(p\log k)\)(其中 \(p\)\(k\) 以内的质数个数)。

而后面那一大坨,可以预处理,就能做到 \(O(k)\)

这样子的话,总复杂度就是 \(O(p\log k + k)\),非常优秀。

当然题目要求没那么严的话直接枚举更加直观,\(O(k^2)\) 的复杂度。

特别鸣谢:Qcfff


四.推式子技巧

1. 总结性式子

(一)

\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[\gcd(i,j)=1] = \sum\limits_{i=1}^{n} \Big(2\cdot \sum\limits_{j=1}^{i}[\gcd(i,j)=1]\Big) -1 =\sum\limits_{i=1}^{n}\Big( 2\varphi(i) \Big)-1 \]

\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\gcd(i,j) =\sum\limits_{d=1}^{n}\Big(d\cdot\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}[\gcd(i,j)=1]\Big) =\sum\limits_{d=1}^{n}\Bigg(d\cdot\Big(\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}( 2\varphi{\scriptstyle(i)} )-1\Big)\Bigg) \]

详细解释在数论习题这篇博客中P2568 GCD这个题里提到。

(二)

\(\color{red}\text{上述两个式子,把 } j \text{ 的上界换成 }m\)

\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=1] =\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\sum\limits_{d\mid \gcd(i,j)}\mu(d) =\sum\limits_{d=1}^{\min(n,m)} \Big(\mu(d) \cdot (\sum\limits_{i=1}^{n}[d\mid i]) \cdot (\sum\limits_{j=1}^{m} [d\mid j])\Big) =\sum\limits_{d=1}^{\min(n,m)} \Big(\mu(d) \lfloor\frac{n}{d}\rfloor \lfloor\frac{m}{d}\rfloor\Big) \]

借助了莫反,详细解释在数论习题这篇博客中P2522 [HAOI2011] Problem b这个题里提到。


\[\begin{aligned} \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\gcd(i,j) &=\sum\limits_{d=1}^{\min(n,m)}d\cdot\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{i=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1] \\&=\sum\limits_{d=1}^{\min(n,m)} \Bigg( d\cdot \sum\limits_{k=1}^{\min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)} \Big(\mu(k) \lfloor\frac{\lfloor\frac{n}{d}\rfloor}{k}\rfloor \lfloor\frac{\lfloor\frac{m}{d}\rfloor}{k}\rfloor \Big) \Bigg) \\&=\sum\limits_{d=1}^{\min(n,m)} \Bigg( d\cdot \sum\limits_{k=1}^{\min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)} \Big(\mu(k) \lfloor\frac{n}{dk}\rfloor \lfloor\frac{m}{dk}\rfloor \Big) \Bigg) \end{aligned}\]

到这里,这个式子已经可以两次数论分块做出来了,但还有优化空间:

注意到:\(dk\le\min(n,m)\),而 \(\lfloor\frac{n}{dk}\rfloor \lfloor\frac{m}{dk}\rfloor\) 同时和 \(d\,,\,k\) 相关,也只和 \(dk\) 相关,于是可以考虑枚举 \(T=dk\)

\[\text{原式}=\sum\limits_{T=1}^{\min(n,m)}\lfloor\frac{n}{T}\rfloor \lfloor\frac{m}{T}\rfloor\sum\limits_{k\mid T}\mu(k)\frac{T}{k} \]

发现 \(\sum\limits_{k\mid T}\mu(k)\frac{T}{k}\) 就是 \(\mu * id=\varphi\),所以:

\[\text{原式}=\sum\limits_{T=1}^{\min(n,m)}\lfloor\frac{n}{T}\rfloor \lfloor\frac{m}{T}\rfloor \varphi(T) \]

一次数论分块即可。

2. 其他小技巧

  1. \(\sum\limits_{d\mid n}\mu(d)=[n=1]\),同理 \([gcd(i,j)=1]=\sum\limits_{d\mid gcd(i,j)}\mu(d)\).

  2. \(\sum\limits_{i=1}^{n} f(i)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{f(i)}1 =\sum\limits_{j=1}^{f(n)}\sum\limits_{i=1}^{n}[j\le f(i)]\),来源于P5170 【模板】类欧几里得算法

  3. \(nm=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=1]\min(\lfloor\frac{n}{i}\rfloor,\lfloor\frac{m}{i}\rfloor)\),无意间发现的,不知道有什么用。

  4. \(d(nm)=\sum\limits_{i\mid n}\sum\limits_{j\mid m}[\gcd(i,j)=1]\)

  5. \(\varphi(ij)=\dfrac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\)

posted @ 2024-01-27 16:26  一匹大宝羊  阅读(57)  评论(0编辑  收藏  举报