zoukankan      html  css  js  c++  java
  • 欧拉函数学习笔记

    原作者:liuzibujian
    原文:https://blog.csdn.net/liuzibujian/article/details/81086324
    本文稍作补充,精细排版。

    前言

    欧拉函数听起来很高大上,但其实非常简单,也是NOIP里的一个基础知识,希望大家看完我的博客能有所理解。
    数论是数学的一个分支,它只讨论正整数的性质,所以以下都是针对正整数进行研究的。

    什么是欧拉函数

    欧拉函数是小于(x)的整数中与(x)互质的数的个数,一般用(varphi(x))表示。特殊的,(varphi (1)=1)

    如何计算欧拉函数

    通式: (varphi(x)=x cdot prod_{i=1}^n{left(1-frac{1}{p_i} ight)},quadvarphi(1)=1)
    其中(p_1,p_2,cdots, p_n)(x)的所有质因数,(x)是正整数。

    那么,怎么理解这个公式呢?对于(x)的一个质因数(p_i),因为(x)以内(p_i)的倍数是均匀分布的,所以(x)以内有(frac{1}{p_i})的数是(p_i)的倍数,那么有(1-frac{1}{p_i})的数不是(p_i)的倍数。再对于(p_j),同理,有(1-frac{1}{p_j})的数不是(p_j)的倍数,所以有((1-frac {1}{p_i})*(1-frac {1}{p_j}))的数既不是(p_i)的倍数,又不是(p_j)的倍数。最后就有(prod_{i=1}^n{(1-frac{1}{p_i})})的数与(x)互质,个数自然就是(xcdotprod_{i=1}^n{(1-frac{1}{p_i})})

    不理解?没关系,举个例子。比如(x=12),12以内有(frac {1}{2})的数是2的倍数,那么有(1-frac {1}{2})的数不是2的倍数(1,3,5,7,9,11),这6个数里又有(frac {1}{3})的数是(3)的倍数,只剩下((1-frac {1}{2})*(1-frac{1}{3}))的数既不是2的倍数,也不是3的倍数(1,5,7,11)。这样剩下的(12*(1-frac{1}{2})*(1-frac{1}{3})),即4个数与12互质,所以(varphi(12)=4)

    积性函数

    先介绍一下什么是积性函数,后面将会用到。
    若当(m)(n)互质时,(f(m∗n)=f(m)∗f(n)),那么(f)是积性函数。
    若对任意正整数,都有(f(m*n)=f(m)*f(n))成立,则(f)是完全积性函数。

    欧拉函数的几个性质

    1. 对于质数(p)(varphi(p)=p−1)

    因为p是质数,所以1到n-1都与n互质。

    2. 若(p)为质数,(x=p^k),则(varphi(x)=p^k-p^{k-1})

    (x)只有一个质因数(p),根据公式(varphi(x)=xcdotprod_{i=1}^n{left(1-frac{1}{p_i} ight)}=xcdot (1-frac{1}{p})=p^kcdotleft(1-frac{1}{p} ight)=p^k-p^{k-1})

    3. 欧拉函数是积性函数,但不是完全积性函数

    (m,n)互质,则(varphi(m∗n)=varphi(m)∗varphi(n))。特殊的,当(m=2)(n)为奇数时,(varphi(2*n)=varphi(n))

    [egin{aligned} varphi(m)* varphi(n) &= m*n * prod_{i=1}^{a_m}{(1-frac{1}{p_i})}*prod_{i=1}^{a_n}{(1-frac{1}{p_i})} \ &= m*n * prod_{i=1}^{a_m+a_n}{(1-frac{1}{p_i})} \ &= varphi(m*n) end{aligned}]

    4. 当(n>2)时,(varphi(n))是偶数

    前几个都可以利用公式证明,这个却不行。

    首先有一个基本事实:若(n>m,\,gcd(n,m)=1),则(gcd(n,n-m)=1)。直白的说,如果与(n)互质的数一个是(m),那么还存在另一个数(n-m)也与n互质。

    (补充:反证法,设(gcd(n,n-m)=k eq 1),则有(a,binmathbb{N}^+,\, a>b)满足(n=ak,\,n-m=bk),得(m=(a-b)k),不符合(gcd(n,m)=1)

    (n)互质的数是成对出现的,所以(varphi(n))必为偶数。但还要排除(m=n-m)的情况:如果(m=n-m),即(n=2∗m),那么(n>2)(n,m)必然不互质,与前提相悖,故(m eq n-m)

    附上一个较为麻烦的证明

    case 1:若(n)为质数,根据性质1,(varphi(n)=n-1)必为偶数。
    case 2:若(n)为合数,则可以写成(n=p_1^{k_1}p_2^{k_2}cdots p_n^{k_n})(p_1,p_2,cdots, p_n)(n)的质因数,(k_1,k_2,cdots,k_n)为对应得指数),而欧拉函数是积性函数,(varphi(n)=varphi(p_1^{k_1})varphi(p_2^{k_2})cdots varphi(p_n^{k_n})),暂且只看(varphi(p_1^{k_1})),根据性质2得到(varphi(p_1^{k_1})=p_1^{k_1}-p_1^{k_1-1}=(p_1-1)p_1^{k_1-1}),其中(p_1-1)必为偶数,偶数乘以任何数均为偶数,故(varphi(n))为偶数。

    5. 小于(n)的数中,与(n)互质的数的总和为(varphi(n)*n/2)(n>1)

    证明这个也要用到上面所说的基本事实。与(n)互质的数一个是(m),那么还存在另一个数(n-m)也与(n)互质。所以与(n)互质的数的平均数是(n/2),而个数又是(varphi(n)),可以得到这些数的和就是(varphi(n)*n/2)

    6. (n=sum_{d|n}{varphi(d)}),即n的因数(包括1和它自己)的欧拉函数之和等于n

    证明1(理性的证明):

    这个证明起来有点麻烦。设(F(n)=sum_{d|n}{varphi(d)})

    (1)如果(n=1)(varphi(n)=1=n),满足(F(n)=n)

    (2)如果(n)是质数,(varphi(n)=nleft(1-frac{1}{n} ight)=n-1),所以(varphi(n)+varphi(1)=1),满足(F(n)=n)

    (3)如果(n)是一个质数(p)的幂,即(n=p^k),因为(p^k)的因数只有(1,p,p^2,p^3,cdots,p^k),根据欧拉函数的性质2((varphi(p^k)=p^k-p^{k-1})),代入计算

    (F(p^k)=varphi(1)+varphi(p)+varphi(p^2)+...+varphi(p^k)=1+(p-1)+(p^2-p)+...+(p^k-p^{k-1})=p^k)

    满足(F(n)=n)

    (4)如果(n)有多个质因子,即(n=p_1^{k_1}p_2^{k_2}cdots p_n^{k_n})

    (4.1)首先证明(F(n))是个积性函数:设(m,n)互质,则要证(F(m∗n)=F(m)∗F(n))

    [egin{aligned} F(m)∗F(n) &= sum_{i|m}{varphi(i)}*sum_{j|n}{varphi(j)} \ &= varphi(i_1)*varphi(j_1)+varphi(i_1)*varphi(j_2)+...+varphi(i_1)*varphi(j_{kn}) \ &quad +varphi(i_2)*varphi(j_1)+varphi(i_2)*varphi(j_2)+...+varphi(i_2)*varphi(j_{kn}) \ &quad +cdots\ &quad +varphi(i_{km})*varphi(j_1)+varphi(i_{km})*varphi(j_2)+...+varphi(i_{km})*varphi(j_{kn}) end{aligned} ]

    其中(i_1,i_2,cdots ,i_{km})(m)的所有因数,(j_1,j_2,cdots,j_{kn})(n)的所有因数之和.

    因为(m)(n)互质,所以它们的因数也必然全都两两互质,而欧拉函数又是个积性函数,即(varphi(i_k*j_k)=varphi(i_k)*varphi(j_k)),那么上式又可以等价于(varphi(i_1*j_1)+varphi(i_1*j_2)+cdots+varphi(i_{km}*j_{kn}))。可以发现,(i_1*j_1,i_1*j_2,cdots,i_{km}*j_{kn})这些数构成了(m∗n)的所有因数。那么这些数的欧拉函数之和就等于(F(m∗n)),所以(F(m∗n)=F(m)∗F(n)),证得F是一个积性函数。

    (4.2)根据(4.1)与(3),(n=p_1^{k_1}p_2^{k_2}cdots p_n^{k_n})时,(F(n)=F(p_1^{k_1})*F(p_2^{k_2})*cdots*F(p_n^{k_n})=p_1^{k_1}p_2^{k_2}cdots p_n^{k_n}=n) 成立。

    综上,(F(n)=n)对所有的正整数(n)成立。

    证明2(感性的证明):

    以12为例。12的因子有1,2,3,4,6,12。把与这些数互质的数列出来:

    1 :1
    2 :1
    3 :1 2
    4 :1 3
    6 :1 5
    12:1 5 7 11
    

    不妨把这些数作为分母,把与这些数互质的数作为分子,写成分数形式:

    1/1
    1/2
    1/3 2/3
    1/4 3/4
    1/6 5/6
    1/12 5/12 7/12 11/12
    

    显然,每一行的数的个数就是该行的分母的欧拉函数值。倘若把这些数都改成以12为分母的数:

    12/12
    6/12
    4/12 8/12
    3/12 9/12
    2/12 10/12
    1/12 5/12 7/12 11/12
    

    可以发现,这些数是以12为分母,1~12为分子的所有数,所以个数为12个。所以与12互质的数的欧拉函数值之和就是12。这样,命题大概就被证明了吧。

    证明2·补充】个人认为更为严谨易懂的说明方法:

    以12为例。我们把以12为分母,1~12为分子的分数列出,设为集合Q(共12个元素):

    Q = {1/12,2/12,3/12,...,11/12,12/12}
    

    如果约分一下会得到:

    Q = {1/12,1/6,1/4,1/3,5/12,1/2,7/12,2/3,3/4,5/6,11/12,1/1}
    

    如果再整理一下,会发现:

    Q = {1/1,  1/2,  1/3,2/3,  1/4,3/4,  1/6,5/6,  1/12,5/12,7/12,11/12}
    

    发现它们对应12的因子(1,2,3,4,6,12)和与这些数互质的数。

    1 :1
    2 :1
    3 :1 2
    4 :1 3
    6 :1 5
    12:1 5 7 11
    

    于是猜想:Q中12个元素就是12个(因子,与因子互质的数)数对,也是12所有的(因子,与因子互质的数)对。如果可以证明这个猜想,那么就证明了“n的因数(包括1和它自己)的欧拉函数之和等于n”。

    现在我们不取12这个特殊值,直接取正整数(n),并设集合(Q)为以(n)为分母、1~(n)为分子的数的集合。要证明上述猜想,只需证明下面两个事实:

    1. 集合(Q)中任意一个元素(q),可以对应唯一一个(因子,与因子互质的数)数对。

      显然,若(q=a/b)(已约分),那么(b)必为(n)的因数,(a,b)必然互质。上述事实成立。

    2. (n)的任意一个(因子,与因子互质的数)数对,可以对应唯一一个集合(Q)中元素(q)

      设这个数对为((a,b)),那么(a)(n)的因数且(a<b)(a,b)互质,设(n=a*k(kin mathbb{N}^+)),则一定存在唯一元素(q=b*k/n)与之对应(分母(b*k<a*k=n),当(a=1)时例外((varphi(1)=1)),取等号((b=a=1)),即对应元素(n/n))。

    由上述两个事实可知,(Q)中元素与(因子,与因子互质的数)数对是一一对应的关系(既不存在(Q)中元素无法对应数对,也不存在数对无法对应(Q)中元素),(Q)中元素的个数即为(n)的(因子,与因子互质的数)数对的个数,也就是“n的因数(包括1和它自己)的欧拉函数之和等于n”。

    求欧拉函数

    埃拉托斯特尼筛求欧拉函数

    观察欧拉函数的公式,(varphi(x)=xprod_{i=1}^n{(1-frac{1}{p_i})}=xprod_{i=1}^n{frac{p_i-1}{p_i}})。我们用phi[x]表示(varphi(x))。可以一开始把phi[x]赋值为(x),然后每次找到它的质因数就(phi[x]=phi[x]/p_i∗(p_i−1))(先除再乘,避免溢出)。当然,若只要求一个数的欧拉函数,可以从1到sqrt(n)扫一遍,若(gcd(i,n)=1)就更新phi[n]。复杂度为(O(log n))(代码就不给了)。那要求1~n所有数的欧拉函数呢?可以用埃拉托斯特尼筛的思想,每次找到一个质数,就把它的倍数更新掉。这个复杂度虽然不是(O(n)),但还是挺快的(据说是(O(n*ln ln n)),关于证明,可以点这里,虽然我看不懂)。
    代码如下:

    void euler(int n){
        for (int i=1;i<=n;i++) phi[i]=i;
        for (int i=2;i<=n;i++){
            if (phi[i]==i){//这代表i是质数
                for (int j=i;j<=n;j+=i){
                    phi[j]=phi[j]/i*(i-1);//把i的倍数更新掉
                }
            }
        }
    }
    

    欧拉筛求欧拉函数

    前提是要懂欧拉筛。每个数被最小的因子筛掉的同时,再进行判断。i表示当前做到的这个数,prime[j]表示当前做到的质数,那要被筛掉的合数就是i*prime[j]。若prime[j]在这个合数里只出现一次(i%prime[j]!=0),也就是iprime[j]互质时,则根据欧拉函数的积性函数的性质,phi[i * prime[j]]=phi[i] * phi[prime[j]]。若prime[j]在这个合数里出现了不止一次(i%prime[j]=0),也就是这个合数的所有质因子都在i里出现过,那么根据公式,(varphi(i * prime[j])=prime[j] * i * prod_{k=1}^n{(1-frac{1}{p_k})} =varphi(i) *prime[j])。复杂度为(O(n))
    还是看代码吧:

    void euler(int n){
    	phi[1]=1;//1要特判 
    	for (int i=2;i<=n;i++){
    		if (flag[i]==0){//这代表i是质数 
    			prime[++num]=i;
    			phi[i]=i-1;
    		}
    		for (int j=1;j<=num&&prime[j]*i<=n;j++){//经典的欧拉筛写法 
    			flag[i*prime[j]]=1;//先把这个合数标记掉 
    			if (i%prime[j]==0){
    				phi[i*prime[j]]=phi[i]*prime[j];//若prime[j]是i的质因子,则根据计算公式,i已经包括i*prime[j]的所有质因子 
    				break;//经典欧拉筛的核心语句,这样能保证每个数只会被自己最小的因子筛掉一次 
    			}
    			else phi[i*prime[j]]=phi[i]*phi[prime[j]];//利用了欧拉函数是个积性函数的性质 
    		}
    	}
    }
    

    总结

    有关欧拉函数的性质,只需做个了解,而求欧拉函数的代码,却是一定要会写的。这只是走进数论世界的第一步。

  • 相关阅读:
    C# MVC模式设置404&500
    jQuery实现滚动条滚动到子元素位置(方便定位)
    Oracle数据库的导出导入
    Oracle之clob字段不能union的问题
    div中内容垂直居中的方法小结
    C#实现Oracle数据库插入clob字段类型数据
    C_结构体_笔记
    Practice_17_01_ABC
    Practice_17_01_GID
    【转】 vim显示行号、语法高亮、自动缩进的设置
  • 原文地址:https://www.cnblogs.com/1024th/p/10807095.html
Copyright © 2011-2022 走看看