欧拉函数

· · 个人记录

\varphi(n)=\sum_{i=1}^n[i\perp n]

特别的,\varphi(1)=1.

1\ [欧拉函数的基本性质]

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

证明略。

  1. \varphi(p^k)=p^k-p^{k-1},当k=1时,即为性质1.

证明:仅有的因子 p 均匀分布,因此p^k个数中有\displaystyle\frac{1}{p}的数不互质。

  1. \forall n>2,\quad\varphi(n)为偶数.

证明:∵\gcd(n,m)=\gcd(n,n-m)n>2 且为偶数时 \gcd(n,n/2)\ne0,即 m\ne n-m.

nm 互质 \Leftrightarrow nn-m 互质,与 n 互质的数成对出现。

\sum_{k=1}^{n}k\times[k\perp n]=\frac{\varphi(n)\times n}{2}

证明:

$n>2$ 时,由性质 3,每一对互质的数之和为 $n$,有 $\dfrac{\varphi(n)}{2}$ 对,总和为$\displaystyle\frac{\varphi(n)\times n}{2}$。 注意: 若考虑到 $n=1$,可以归纳为 $$\sum_{k=1}^{n}k\times[k\perp n]=\frac{\varphi(n)\times n+[n=1]}{2}$$

2\ [求欧拉函数]

n的唯一分解为p_1^{\alpha_1}\cdot p_2^{\alpha_2}\cdots p_k^{\alpha_k},则 \displaystyle\varphi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})\cdots (1-\frac{1}{p_k})=n\prod_{p_i\mid n}(1-\frac{1}{p_i}).

证明:n的所有因子均为绝对均匀分布,因此p_1筛去\displaystyle \frac{1}{p_1}的数,p_2剩下的里再筛去\displaystyle \frac{1}{p_2}的数\cdots以此类推。

因此我们可以分解质疑数,每遇到一个素因子p,乘以(1-\displaystyle\frac{1}{p}),分级质因数复杂度O(\sqrt n).

3\ [筛欧拉函数]

初始化所有 \varphi(i)=i,每当遇到素数 p 时,将其所有倍数乘以 1-\displaystyle\frac{1}{p}

若遇到 \varphi(i)=i 的,则表明其未被更改过,为素数。

欧拉函数的线性筛法基于一条重要性质。

欧拉函数是积性函数.

积性函数:若\forall n\perp m,f(nm)=f(n)\cdot f(m),则称f(x)为积性函数。若\forall n,m均成立,则称为完全积性函数,欧拉函数不是完全积性函数。

证明:

\displaystyle\varphi(n)=n\prod_{p_i\mid n}(1-\frac{1}{p_i}),\varphi(m)=m\prod_{p_j\mid m}(1-\frac{1}{p_j})

又∵n\perp mp_i\not =p_j,所以

\displaystyle \varphi(n) \cdot \varphi(m)=nm\prod_{p_i\mid n}(1-\frac{1}{p_i})\prod_{p_j\mid m}(1-\frac{1}{p_j})=nm\prod_{p_k\mid nm}(1-\frac{1}{p_k})=\varphi(nm).

同素数的线性筛法,我们考虑让每个数只被最小素因子筛出。

因此,我们仍需借助已有素数集合。

对于当前的 i,枚举 ip_j 倍。

$$\varphi(ip_j)=\varphi(i)\cdot\varphi(p_j)=\varphi(i)\cdot(p_j-1).$$ 当遇到第一个 $p_j\mid i$ 时,$i$ 的因子包含 $p_j$, 所以 $p_j$ 的因子一定是 $i$ 的因子, 故有 $$\varphi(ip_j)=ip_j\cdot\prod_{k\mid i}(1-\frac{1}{k})=\varphi(i)\cdot p_j$$ 此时(当遇到第一个 $p_j\mid i$ 时)应结束循环,否则下一个被计算的合数为 $p_{j+1}i$,而 $p_j\mid i$,$p_{j+1}$ 显然不是 $p_{j+1}i$ 的最小素因子,而我们只想让每个数被其最小素因子筛出,故结束循环。 复杂度 $O(n)$。 - 【代码】 ```cpp void sieve(int n) { phi[1] = 1; for(int i = 2; i <= n; ++i) { if(!mark[i]) pri[++tot] = i, phi[i] = i - 1; for(int j = 1; j <= tot and i * pri[j] <= n; ++j) { mark[i * pri[j]] = true; if(i % pri[j]) phi[i * pri[j]] = phi[i] * (pri[j] - 1); else { phi[i * pri[j]] = phi[i] * pri[j]; break; } } } } ```