欧拉函数

匿名 (未验证) 提交于 2019-12-02 23:42:01

\(\varphi(x)\)表示\(x\)以内与\(x\)互质的个数
\(\varphi(x)=x*\prod\limits_{i=1}^n(1-\dfrac{1}{p_i})\) \(p_i\)为x的质因数
特殊的 \(\varphi(1)=1\)

其中\(p_1,p_2……p_n\)Ϊ\(x\)的所有质因数(\(x\)是正整数)
那么,怎么理解这个公式呢?
对于\(x\)的一个质因数\(p_i\),因为\(x\)以内\(p_i\)的倍数是均匀分布的,所以\(x\)以内有\(\frac {1}{p_i}\)的数是\(p_i\)的倍数
对应的,有\(1-\dfrac {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\)的倍数

当有函数\(f(x)\)\(m\)\(n\)互质时,\(f(m)*f(n)=f(m*n)\)称为积性函数
对任意整数\(m\)\(n\)\(f(m)*f(n)=f(m*n)\)称为完全积性函数

  • 对于质数\(p\)\(\varphi(p)=p-1\)
    证明:这貌似不需要证明吧qwq

  • 对于质数p,\(\varphi(p^k)=p^k-p^{k-1}\)
    证明:\(\varphi(p^k)=p^k*(1-\dfrac{1}{p})\)

  • 欧拉函数是积性但飞完全积性函数,对于\(m\)\(n\)互质时,有\(\varphi(m)*\varphi(n)=\varphi(m*n)\)
    特殊的,\(m=2\)\(n\)为奇数,\(\varphi(m)*\varphi(n)=\varphi(n)\)
    证明:\(m\)\(n\)互质,说明没有公共质因数,\(m*n\)质因数为\(m\)的质因数+\(n\)的质因数

  • \(n>2\)时,\(\varphi(n)\)为偶数
    证明:有基本事实\(gcd(a,b)=1\) \(gcd(a,a-b)=1\),说明质因数都是成对出现的

  • 对于小于\(n\)且与\(n\)互质的数,总和=\(\varphi(n)*n/2\)
    证明:对于与\(n\)互质的数\(m\),有对立的\(n-m\)\(n\)互质,\(m\)\(n-m\)的平均数又为\(n/2\)\(\varphi(n)\)又为偶数

  • \(n=\sum\limits_{d|n}\varphi(d)\)
    设函数\(F(n)=\sum\limits_{d|n}\varphi(d)\)
    \(m\)\(n\)互质
    \(F(m)*F(n)=\sum\limits_{i|m}\varphi(i)*\sum\limits_{j|n}\varphi(j)\)
    \(=\varphi(i_1)*\varphi(j_1)+\varphi(i_1)*\varphi(j_2).....+\varphi(i_{km})*\varphi(j_{kn})\)
    \(=\varphi(i_1*j_1)+\varphi(i_1*j_2).....+\varphi(i_{km}*j_{kn})\) m与n互质,故因数也必全互质
    \(=\sum\limits_{k|m*n}\varphi(k)\) 可以发现,\(i_1*j_1,i_1*j_2.....i_{km}*j_{kn}\)这些数为\(n*m\)的因数
    \(=F(m*n)\)
    设合数\(n=p1^{k1}*p2^{k2}.....*pm^{km}\)\(F(n)=F(p1^{k1}*F(p2^{k2}).....*F(pm^{km}))\)
    利用性质2易证\(F(pm^{km})=pm^{km}\),则\(F(n)=p1^{k1}*p2^{k2}.....*pm^{km}=n\)

单个:\(2\)~\(\sqrt{(n)}\)扫一遍就好了,素数怎么求这个就怎么求
要是求<=n所有数的欧拉函数呢?
埃拉托斯特尼筛求欧拉函数 \(O(n(log(n))(loglogn))\)
就是普通的找质数,把倍数都筛一遍(质因数的贡献)

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)//把i的倍数筛一遍                 phi[j]=phi[j]/i*(i-1); }

欧拉筛求欧拉函数 \(O(n)\)
先来了解一下欧拉筛

for(int i=2;i<=n;i++){     if(!vis[i])//不是目前找到的素数的倍数          prime[cnt++]=i;//找到素数~      for(int j=0;j<cnt&&i*prime[j]<=n;j++){         vis[i*prime[j]]=true;//找到的素数的倍数不访问          if(i%prime[j]==0)              break;//关键!!!!      } }

很多人对 $ if(i%prime[j]==0) break; $ 这一句都不太理解
找到一种很好的解释:
\(i\)\(prime[j]\)的倍数时,\(i=k*prime[j]\),如果继续运算 \(j+1\)\(i*prime[j+1]=prime[j]*k*prime[j+1]\)
这里\(prime[j]\)是最小的素因子,当\(i=k*prime[j+1]\)时会重复
这里是利用最小素因子优化,使得欧拉筛达到了优秀的线性\(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]];//利用了欧拉函数是个积性函数的性质      }     } }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!