• 11-欧拉函数详解


    (转载)https://blog.csdn.net/qq_39922639/article/details/77511761

                     常见函数讲解1:欧拉函数

    版权声明:假如读者觉得本文写的不错,欢迎转发!不过请附上本文的链接。 https://blog.csdn.net/qq_39922639/article/details/77511761

    前言

    作者在OI生活早期的时候,经常遇到一些数学题不会,点开题解发现许多跟数论上的函数有关,题解的语言又晦涩难懂,从此对数学心有余悸,相信许多OIer也同样是如此。这几篇博客,作者将对OI数论中常出现的几个函数进行解读,希望读者能解开对数学的心结。


    积性函数


    概念

    积性函数是对数论中一系列有特殊性质函数的统称,性质如下:

     
    gcd(a,b)=1, f(ab)=f(a)f(b),f若gcd(a,b)=1, f(ab)=f(a)f(b),那么f则是积性函数。

    特别地,假如对于任意的a、b,即gcd(a,b)1gcd(a,b)≠1也有f(ab)=f(a)f(b)f(ab)=f(a)f(b),那么称f是完全积性函数。

    小扩展

    一个有趣的事实:

     
    g(n)=d|nf(d),gf对于函数g(n)=∑d|nf(d),如果g是积性函数,那么f也是积性函数。
    上面那个式子中,d|nd|n的意思是在枚举nn的所有约数。证明的话可以使用归纳法,作者将会在后面补上一篇关于上述式子证明的博客,读者也可以尝试自己推导一下。

    常见积性函数

    1、e(n)=[n=1]e(n)=[n=1]. 
    单位元函数,即只有在nn为1的时候函数值为1,其它时候函数值均为0.

    2、id(n)=nid(n)=n. 
    这个可以理解成就是y=xy=x.

    3、1(n)=11(n)=1. 
    可以理解成直线y=1y=1.

    4、φ(n)=ni=1[gcd(i,n)=1]φ(n)=∑i=1n[gcd(i,n)=1]. 
    欧拉函数,本次要讲解的主角,表示小于n且与n互质的正整数的个数.

    5、μ(n)={0, d>1,d2|n(1)k,n=ki=1piμ(n)={(−1)k,n=∏i=1kpi0, ∃d>1,d2|n 
    莫比乌斯函数,本文不作探究,详见下一篇博客。


    小结

    积性函数在数论中十分常见,一个函数假如有积性那么就多了许多解析的方法,在你涉(shua)猎(ti)的数值达到一定量的时候会发现积性是个亲切的东西,比如我们可以利用欧拉函数和莫比乌斯函数的积性来进行线性筛,O(n)时间求得所有欧拉函数、莫比乌斯函数值。


    欧拉函数

    注:阅读以下内容时请拿出笔和纸,下面涉及的计算量比较大,用笔算一算将助于理解。


    概念

    正如上一节所述,欧拉函数φ(n)φ(n)表示的含义即是小于n且与n互质的正整数的个数。定义式如下:

     
    φ(n)=i=1n[(gcd(i,n)=1]φ(n)=∑i=1n[(gcd(i,n)=1]

    基本性质

    • 1.对于一个质数p,φ(p)=p1.φ(p)=p−1.

    证明:根据质数的定义,对于任意一个不是p倍数的正整数x,总有gcd(p,x)=1gcd(p,x)=1,即p与x互质。在1~p之间,只有1××p是p的倍数,故在1~p中,与p互质的数为1到p-1,共p-1个,φ(p)=p1φ(p)=p−1。

    • 2.对于一个质数p,φ(pk)= pkpk1= pk1×(p1)= pk1×φ(p)φ(pk)= pk−pk−1= pk−1×(p−1)= pk−1×φ(p).

    证明:我们知道,在1~p之间与p不互质的数共1个,在1~2××p之间与p不互质的数共2个……在1~pk1×ppk−1×p之间有pk1pk−1个。所以在1~pkpk之间与p不互质的数有pk1pk−1个,互质的那就是pkpk1pk−pk−1,故φ(pk)= pkpk1φ(pk)= pk−pk−1,即第二个式子。然后提取公因数pk1pk−1得到第三个式子。结合性质1得到第四个式子。

    • 3.对于一个数n,我们将其质因数分解为n=ki=1prii∏i=1kpiri,那么
       
      φ(n)= i=1kφ(prii)= i=1kpri1×(p1)= n×i=1k(11pi)φ(n)= ∏i=1kφ(piri)= ∏i=1kpri−1×(p−1)= n×∏i=1k(1−1pi)
      .

    证明:由于欧拉函数有积性,φ(ab)=φ(a)φ(b)φ(ab)=φ(a)φ(b),所以有φ(n)= ki=1φ(prii)φ(n)= ∏i=1kφ(piri)。结合性质2的第三个式子,我们可以得到第三个式子。对于第三个式子,我们提取一个公因子p,得到

     
    i=1kpri×(11pi)= (i=1kpri)×(i=1k(11pi))= n×i=1k(11pi).∏i=1kpri×(1−1pi)= (∏i=1kpri)×(∏i=1k(1−1pi))= n×∏i=1k(1−1pi).
    得证。

    扩展性质

    • 1.假如a,b不互质,那么φ(ab)φ(ab)等于什么呢?
     
    d=gcd(a,b)φ(ab)= φ(a)φ(b)dφ(d).结论:令d=gcd(a,b),则φ(ab)= φ(a)φ(b)dφ(d).

    证明:

    将a、b、d质因数分解成

     
    a=i=1mpr1ii b=i=1mpr2ii d=i=1mpmin(r1i, r2i)ia=∏i=1mpir1i, b=∏i=1mpir2i, d=∏i=1mpimin(r1i, r2i)
    那么a×ba×b可以分解成
     
    a×b=i=1mpr1i+r2iia×b=∏i=1mpir1i+r2i
    结合基本性质3,有:
     
    φ(a)=i=1mφ(pr1ii) φ(b)=i=1mφ(pr2ii) φ(d)=i=1mφ(pmin(r1i, r2i)i)φ(a×b)=i=1mφ(pr1i+r2ii)φ(a)=∏i=1mφ(pir1i), φ(b)=∏i=1mφ(pir2i), φ(d)=∏i=1mφ(pimin(r1i, r2i)),φ(a×b)=∏i=1mφ(pir1i+r2i)

    所以,我们将原式转化成如下形式:
     
    i=1mφ(pr1i+r2ii)=mi=1φ(pr1ii)×mi=1φ(pr2ii)×mi=1pmin(r1i, r2i)imi=1φ(pmin(r1i, r2i)i)∏i=1mφ(pir1i+r2i)=∏i=1mφ(pir1i)×∏i=1mφ(pir2i)×∏i=1mpimin(r1i, r2i)∏i=1mφ(pimin(r1i, r2i))
    结合基本性质3,进一步转化:
     
    =i=1mpr1i+r2i1i(pi1)左边=∏i=1mpir1i+r2i−1(pi−1)
     
    =mi=1pr1i1i(pi1)×mi=1pr2i1i(pi1)×mi=1pmin(r1i, r2i)imi=1pmin(r1i, r2i)1i(pi1)右边=∏i=1mpir1i−1(pi−1)×∏i=1mpir2i−1(pi−1)×∏i=1mpimin(r1i, r2i)∏i=1mpimin(r1i, r2i)−1(pi−1)
     
    = i=1mpr1i1i(pi1)× pr2i1i(pi1)× pmin(r1i, r2i)ipmin(r1i, r2i)1i(pi1)= ∏i=1mpir1i−1(pi−1)× pir2i−1(pi−1)× pimin(r1i, r2i)pimin(r1i, r2i)−1(pi−1)

    对上面那一长串式子进行约分,我们发现右边等于左边,得证。
    • 2.对于任意正整数n,φ(n)φ(n)与nn有什么样的关系?
     
    n=d|nφ(d).结论:n=∑d|nφ(d).

    证明: 
    我们不妨换个角度思考一下。

    我们知道n=ni=11n=∑i=1n1,如何解读这个简单式子呢?我们把n看成一个确定的数,这个式子就可以理解成:枚举1~n中的每一个数i,每个f(n,i)f(n,i)只产生1的贡献,统计每个f(n,i)f(n,i)产生的贡献和。

    换句话说,我们本来想统计ni=1f(n,i)∑i=1nf(n,i),但由于每一个f(n,i)f(n,i)都等于1,所以变成了ni=11.∑i=1n1.

    于是,现在的关键变成了寻找这个特殊的f(n,i).f(n,i). 正好我们发现了一个。

    我们知道,在1~n中的每一个i,它与n的最大公约数有且仅有一个,且最大公约数一定在1~n这个范围之内。我们可以令f(n,i)=[gcd(n,i)=d]f(n,i)=[gcd(n,i)=d],([中括号]内的表达式若为真则值为1,否则为0)然后在1~n中枚举最大公约数d,对每一个i进行判断,不就满足上面的式子了!

    也就是:

     
    n=i=1n1=d=1ni=1n[gcd(n,i)=d].n=∑i=1n1=∑d=1n∑i=1n[gcd(n,i)=d].

    其中d枚举的是最大公约数,i枚举的是1~n中的每一个i,f(n,i)=[gcd(n,i)=d]f(n,i)=[gcd(n,i)=d]。

    其实我们发现,d的取值一定是n的约数,并不需要枚举1~n中的所有数,所以有:

     
    n=d=1ni=1n[gcd(n,i)=d]=d|ni=1n[gcd(n,i)=d].n=∑d=1n∑i=1n[gcd(n,i)=d]=∑d|n∑i=1n[gcd(n,i)=d].

    对上面第三个式子进一步转化:

     
    d|ni=1n[gcd(n,i)=d]=d|ni=1n[gcd(nd,id)=1]×[ d|i ]∑d|n∑i=1n[gcd(n,i)=d]=∑d|n∑i=1n[gcd(nd,id)=1]×[ d|i ]

    观察上面第二个式子,之所以转化成这么鬼畜的东西是因为第一个式子中[gcd(n,i)=d][gcd(n,i)=d]这个式子值为1的时候,dd一定是ii的约数,所以在第二个式子中也必须要满足dd是ii的约数时,[gcd(nd,id)=1][gcd(nd,id)=1]才有贡献。

    转化到这里,细心的读者估计也发现了,第二个式子中idid的取值范围实际上是1~ndnd,所以ni=1[gcd(nd,id)=1]×[ d|i ]∑i=1n[gcd(nd,id)=1]×[ d|i ] 其实就是在枚举在1~ndnd中,有多少个数与ndnd互质,这不就是φ(nd)φ(nd)吗?

    至此,我们便将原式转化成:

     
    n=d|ni=1n[gcd(nd,id)=1]×[ d|i ]=d|nφ(nd).n=∑d|n∑i=1n[gcd(nd,id)=1]×[ d|i ]=∑d|nφ(nd).

    得证。

    其实还有一种有趣的证明,我会在后面连同上面积性函数小扩展的证明一同发布一篇博客。


    欧拉函数求法

    • 1.质因数分解.

    假如我们只想求解1个或者少量正整数的欧拉函数,那么

    根据基本性质3,

     
    φ(n)=n×i=1k(11pi)=n×i=nk(pi1)piφ(n)=n×∏i=1k(1−1pi)=n×∏i=nk(pi−1)pi

    我们可以把n质因数分解,然后带入上述第三个式子求得。时间复杂度O(n−−√n).

    int get_phi(int n){
        int back = n;
        for(int p = 2; p*p <= n; ++ p){
            if(n%p == 0){
                back = back/p*(p-1);
                while(n%p == 0)
                    n /= p;
            }
        }
        if(n != 1)
            back = back/n*(n-1);
    
        return back;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 2.线性筛

    注:默认读者已经掌握线性筛质数.

    假如想要求1~n范围内所有数的欧拉函数,那么上面的质因数分解法的复杂度会高达O(nn−−√)O(nn),有没有更快速的方法呢?

    由于欧拉函数有积性,所以结合扩展性质1:

     
    d=gcd(a,b)φ(ab)= φ(a)φ(b)dφ(d).令d=gcd(a,b),则φ(ab)= φ(a)φ(b)dφ(d).

    我们可以通过线性筛质数,在筛出合数x×prijx×prij的同时计算出φ(x×prij)φ(x×prij)。(注:prijprij为已经筛出来的质数,见线性筛)

    不过,需要分2种情况计算:

    1. x与prijprij互质.

      这种情况比较简单。由于d=1d=1,φ(d)=1φ(d)=1,所以

       
      φ(x×prij)=φ(x)×φ(prij)φ(x×prij)=φ(x)×φ(prij)
      直接计算即可。
    2. x与prijprij不互质. 
      这种情况下,xx只可能是prijprij的倍数,故d=gcd(x,prij)=prijd=gcd(x,prij)=prij,所以:

       
      φ(x×prij)=φ(x)φ(prij)prijφ(prij)=φ(x)×prij.φ(x×prij)=φ(x)φ(prij)prijφ(prij)=φ(x)×prij.

      带入计算即可。
    bool vis[1000005];
    int tot=0, pri[1000005], phi[1000005];
    
    void Get_phi(int N){
        phi[1] = 1;
        for(int i=2; i<=N; ++i){
            if(!vis[i]){
                pri[++tot] = i;
                phi[i] = i-1;
            }
            for(int j=1,x; j<=tot&&(x=i*pri[j])<=N; ++j){
                vis[x] = true;
                if(i%pri[j] == 0){
                    phi[x] = phi[i]*pri[j];
                    break;
                }
                else phi[x] = phi[i]*phi[pri[j]];
            }
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    小结

    欧拉函数的讲解就先告一段落,其实欧拉函数与其它的函数甚至定理有许多关联的地方,我将在今后为大家讲解。假如有地方没有听懂,随时欢迎骚扰。

  • 相关阅读:
    定制事件 观察者模式
    定时器的高级运用 优化
    tamper-proof 对象 nonextensible对象 sealed对象 frozen对象
    函数柯理化
    跨域 Ajax 其他可选技术 异步
    Ajax 跨域 异步 CORS
    原样输出html标签
    JavaScript
    css 中name的用途
    iview 按需引入解决加载慢的问题
  • 原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/9522564.html
Copyright © 2020-2023  润新知