zoukankan      html  css  js  c++  java
  • 欧拉函数专题

    一、欧拉函数概念

    \(ϕ(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})\)展开,发现就是上面的东东了,证明完毕。

  • 相关阅读:
    geoserver发布地图服务WMTS
    geoserver发布地图服务WMS
    geoserver安装部署步骤
    arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
    arcgis api 3.x for js 入门开发系列十三地图最短路径分析(附源码下载)
    cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)
    arcgis api 3.x for js 入门开发系列十二地图打印GP服务(附源码下载)
    arcgis api 3.x for js 入门开发系列十一地图统计图(附源码下载)
    arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
    arcgis api 3.x for js入门开发系列九热力图效果(附源码下载)
  • 原文地址:https://www.cnblogs.com/littlehb/p/15213612.html
Copyright © 2011-2022 走看看