一、欧拉函数概念

\(ϕ(n)\)表示\(n\)的欧拉函数值,代表了从\(1\)\(n\)\(n\)互质的数的个数,例如\(ϕ(8)=4\) 因为\(1,3,5,7\)均和\(8\)互质。特殊的\(ϕ(1)=1\)

二、欧拉函数公式

根据算法基本定理,数字\(n\)必然可以描述为如下数学公式:

$\large n={p_1}^{\alpha_1} * {p_2}^{\alpha_2} * {p_3}^{\alpha_3} * ... * {p_k}^{\alpha_k}$
欧拉函数的公式:
$\large ϕ(n)=n*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})*(1-\frac{1}{p_3})*(1-\frac{1}{p_4})*……*(1-\frac{1}{p_k})$

其中\(p_1, p_2……p_k\)\(n\)的所有质因数,\(n\)是不为\(0\)的整数。\(φ(1)=1\)(唯一和\(1\)互质的数就是\(1\)本身)。
注意:欧拉函数与幂指数$ \alpha_i $无关,只与质数因子有关。

三、求单个数字的欧拉函数

#include <bits/stdc++.h>

using namespace std;

/**
 * 功能:欧拉函数
 * @param x
 * @return
 */
int phi(int x) {
    int res = x;
    for (int i = 2; i <= x / i; i++)
        if (x % i == 0) {
            res = res / i * (i - 1);
            while (x % i == 0) x /= i;
        }
    if (x > 1) res = res / x * (x - 1);
    return res;
}

int main() {
    cout << phi(2) << endl;
    cout << phi(8) << endl;
    return 0;
}

四、筛法求欧拉函数

1、依托于线性筛法,可以顺带求出欧拉函数值。如果对数论了解更多,会知道线性筛法还可以求出很多其它的东西。

2、\(phi[1]=1\)

3、对区间内每个数进行分情况讨论:

  • 如果这个数是质数,那么质数\(i\)的欧拉函数值是\(phi[i]=i-1\)
    比如\(7\),那么\(1-6\)当中有多少个数与\(7\)互质呢?显然\(6\)个都是嘛。

  • 数字\(i\)在被\(primes[j]\)尝试筛的过程中:(这里设 \(p_j=primes[j]\)以简便下面的书写)
    如果\(i\ \% \ p_j = 0\), 那么 \(phi[i * p_j] = phi[i] * p_j\)
    证明:

    \(\because\) \(i={p_1}^{\alpha_1} * {p_2}^{\alpha_2} * {p_3}^{\alpha_3} * ... *{p_j}^{\alpha_j}\) 【算术基本定理】
    $phi[i]= i * (1- \frac{1}{p_1}) * (1- \frac{1}{p_2}) * (1- \frac{1}{p_3}) * ... * (1- \frac{1}{p_j}) $ 【欧拉公式】

    \(phi[p_j*i]\)分解质数因数的结果,只比\(phi[i]\)多分解了一个\(p_j\),而 \(i \ \% \ p_j = 0\) 说明\(phi[i]\)中存在\(p_j\)因子,只不过指数增加了\(1\)个。

    \(\therefore\) \(p_j * i ={p_1}^{\alpha_1} * {p_2}^{\alpha_2} * {p_3}^{\alpha_3} * ... *{p_j}^{\alpha_j+1}\)

    \(\therefore\) $phi[p_j * i]= phi[i] * p_j $ 【证毕】

  • 如果\(i\ \% \ p_j > 0\), 那么 \(phi[i * p_j] = phi[i] * (p_j-1)\)
    证明:
    \(\because\) \(i={p_1}^{\alpha_1} * {p_2}^{\alpha_2} * {p_3}^{\alpha_3} * ... *{p_k}^{\alpha_k}\)

    $phi[i]= i * (1- \frac{1}{p_1}) * (1- \frac{1}{p_2}) * (1- \frac{1}{p_3}) * ... * (1- \frac{1}{p_k}) $

    \(phi[p_j*i]\)分解质数因数的结果,只是比\(phi[i]\)多分解了一个\(p_j\),而 \(i \ \% \ p_j>0\) 说明\(phi[i]\)中不存在\(p_j\)这个因子,需要写上去。

    \(p_j * i ={p_1}^{\alpha_1} * {p_2}^{\alpha_2} * {p_3}^{\alpha_3} * ... * {p_k}^{\alpha_k} * {p_j}^{1}\)

    \(\therefore\) $phi[p_j * i]= p_j * i * (1- \frac{1}{p_1}) * (1- \frac{1}{p_2}) * (1- \frac{1}{p_3}) * ... * (1- \frac{1}{p_k}) * (1- \frac{1}{p_j}) $

    \(\therefore\) $phi[p_j * i]= p_j * phi[i] * (1 - \frac{1}{p_j}) = phi[i] * ( p_j -1) $ 【证毕】

#include <bits/stdc++.h>

using namespace std;

//筛法求欧拉函数
typedef long long LL;

const int N = 1000010;
int primes[N];  //保存的是每一个质数
int size;       //cnt代表质数下标,就是到第几个了
int phi[N];     //欧拉函数值,一般叫Φ,函数名不能是希腊字母,所以转为phi
bool st[N];     //代表是不是已经被筛掉了
LL res;         //结果

void get_eulers(int n) {
    //1的欧拉函数值
    phi[1] = 1;
    //如果当前i没有被筛过,说明当前i是一个质数
    for (int i = 2; i <= n; i++) {
        if (!st[i]) {
            //增加一个质数
            primes[size++] = i;
            phi[i] = i - 1;
        }
        for (int j = 0; primes[j] <= n / i; j++) {
            int t = primes[j] * i;
            st[t] = true;
            if (i % primes[j] == 0) {
                phi[t] = phi[i] * primes[j];
                break;
            } else
                phi[t] = phi[i] * (primes[j] - 1);
        }
    }
}

int main() {
    //优化读入
    ios::sync_with_stdio(false);
    int n;
    cin >> n;

    //线性筛质数的办法,在过程中求得欧拉函数
    get_eulers(n);

    for (int i = 1; i <= n; i++) res += phi[i];
    //输出结果
    cout << res << endl;

    return 0;
}

五、欧拉函数的证明

欧拉函数的证明是使用的融斥原理,从定义出发:

欧拉函数专题
(1)对数字$N$进行质因数分解: $N={p_1}^{\alpha_1} * {p_2}^{\alpha_2} * {p_3}^{\alpha_3} * ... * {p_k}^{\alpha_k}$

(2)把\(p_1\)的倍数从\(N\)中减去,因为这些数都肯定不是与\(N\)互质的,有约数\(p_1\)嘛。那需要减去多少个呢?
\(\frac{N}{p_1}\)个.

(3) 把\(p_2,p_3,...,p_k\)的倍数都减去吧,分别减去\(\frac{N}{p_2}\),\(\frac{N}{p_3}\),...,\(\frac{N}{p_k}\)个。

(4) 这么干是减多了的,比如某个数,是\(p_2\)的倍数,也是\(p_3\)的倍数,就减了两回,还需要再加回来\(p_i * p_j\)的倍数,就是 + \(\frac{N}{p_1 * p_2}\)+ \(\frac{N}{p_1 * p_3}\)+ \(\frac{N}{p_1 * p_k}\)+ ....

(5)将公式\(\phi(N)=N * (1-\frac{1}{p_1}) * (1-\frac{1}{p_2}) * (1-\frac{1}{p_3}) * ... * (1-\frac{1}{p_k})\)展开,发现就是上面的东东了,证明完毕。

相关文章:

  • 2022-12-23
  • 2021-08-31
猜你喜欢
  • 2022-02-19
  • 2021-10-05
  • 2021-11-01
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-02
相关资源
相似解决方案