第二十六章 数论——欧拉函数(详解与证明)
- 欧拉函数
- 1、互质
- 2、欧拉函数的定义
- 3、欧拉函数的公式
- 4、欧拉函数的证明
- 5、欧拉函数的使用
- (1)问题一:
- 思路
- 代码
- (2)问题二:
欧拉函数
1、互质
如果gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1,则说明两个数互质。即如果两个数最大公约数是1,那么这两个数就是互质的。
比如14和15
14的约数:1,2,7,14
15的约数:1,3,5,15
二者的最大公约数是1,即gcd(14,15)=1gcd(14,15)=1gcd(14,15)=1,所以14和15互质。
2、欧拉函数的定义
对于一个数nnn,从111到nnn中,与nnn互质的个数记作Φ(n)\Phi (n)Φ(n),那么这个Φ(n)\Phi (n)Φ(n)就i被称作欧拉函数。
比如:
Φ(6)=2\Phi (6)=2Φ(6)=2
因为,
1,2,3,4,5,6中与6互质的是1和5。
3、欧拉函数的公式
根据算数基本定理,该合数可以写成有限个质数的乘积,即:
n=p1k∗p2m∗p3x...pnwn=p_1^k*p_2^m*p_3^x...p_n^wn=p1k∗p2m∗p3x...pnw
那么Φ(n)=n∗(p1−1p1)∗(p2−1p2)∗...∗(pn−1pn)\Phi (n)=n*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p2})*...*(\frac{p_n-1}{p_n})Φ(n)=n∗(p1p1−1)∗(p2p2−1)∗...∗(pnpn−1)
这就是著名的欧拉函数。
我们可以验证一下:
6=2∗36=2*36=2∗3
Φ(6)=6∗2−12∗3−13=2\Phi (6)=6*\frac{2-1}{2}*\frac{3-1}{3}=2Φ(6)=6∗22−1∗33−1=2
特殊地,
如果一个数是质数,我假设这个质数是ppp,质数的算数基本定理的表达式就是本身,所以
Φ(p)=p∗(p−1p)=p−1\Phi (p)=p*(\frac{p-1}{p})=p-1Φ(p)=p∗(pp−1)=p−1
所以,如果一个数是质数,那么这个数ppp:
Φ(p)=p−1\Phi (p)=p-1Φ(p)=p−1
那么这个函数怎么证明呢?
我们继续向下看:
4、欧拉函数的证明
5、欧拉函数的使用
(1)问题一:
思路
现在问题的关键其实就是质因数的分解,而质因数的分解,作者在前面的文章详细讲解过分解方式:
传送门:质因数的分解
代码
#include<iostream>
using namespace std;long long phi(int a)
{long long ans=a;for(int i=2;i<=a/i;i++){if(a%i==0)ans=ans*(i-1)/i;while(a%i==0)a/=i;}if(a>1)ans=ans*(a-1)/a;return ans;
}int main()
{int n;cin>>n;for(int i=0;i<n;i++){int a;scanf("%d",&a);cout<<phi(a)<<endl;}return 0;
}
(2)问题二:
思路
这道题的关键在于求出1到n之间的每个数字的欧拉函数之和,那么我们可以将1到n之间的数字分成三类:
case1case1case1
Φ(1)=1\Phi (1)=1Φ(1)=1
case2case2case2
Φ(质数)=质数−1\Phi(质数)=质数-1Φ(质数)=质数−1
case3case3case3
合数的话,则需要分解质因数计算求解。
Φ(n)=n∗(p1−1p1)∗(p2−1p2)∗...∗(pn−1pn)\Phi (n)=n*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p2})*...*(\frac{p_n-1}{p_n})Φ(n)=n∗(p1p1−1)∗(p2p2−1)∗...∗(pnpn−1)
涉及到数的筛选问题:
我们可以联想到之前所学的两种筛法:埃氏筛法和欧拉筛法
不了解这两个筛法的同学建议先去看一下作者之前的讲解:
埃氏筛法和欧拉筛法
我们这里采用欧拉筛法。
那么欧拉筛和欧拉函数怎么结合求呢?
首先我们根据欧拉函数公式:
Φ(n)=n∗(p1−1p1)∗(p2−1p2)∗...∗(pn−1pn)\Phi (n)=n*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p2})*...*(\frac{p_n-1}{p_n})Φ(n)=n∗(p1p1−1)∗(p2p2−1)∗...∗(pnpn−1)
可以知道,结果只和质数本身有关,和他的指数是无关的。
另外,我们的欧拉筛是用来筛质数的,质数的欧拉函数也是很好求的,那么我们思考一下:
能否用质数的欧拉函数结果去求解合数的欧拉函数?
primes[j]primes[j]primes[j]是质数,所以我们的Φ(primes[j])=primes[j]−1\Phi(primes[j])=primes[j]-1Φ(primes[j])=primes[j]−1
我们欧拉筛的第二层循环中,我们存在这样一个判断 imodprimes[j]是否等于0i\ mod\ primes[j]是否等于0i mod primes[j]是否等于0
第一种情况:imodprimes[j]==0第一种情况:i\ mod\ primes[j]==0第一种情况:i mod primes[j]==0
这个判断说明,primes[j]primes[j]primes[j]是iii的一个质因数。
也就是说,Φ(i)\Phi(i)Φ(i)中存在一项(1−1primes[j])(1-\frac{1}{primes[j]})(1−primes[j]1)
而我们假设k=i∗primes[j]k=i*primes[j]k=i∗primes[j],那么kkk的算数基本定理的表达式当中只是比iii的表达式中,primes[j]primes[j]primes[j]的这一项所对的指数加了1而已。
也就是说,
i∗primes[j]i*primes[j]i∗primes[j]和iii所含的质因数种类是相同的。
所以二者的欧拉函数中,后面的多项式乘积都是一样的,只是前面的系数nnn不同,因此我们可以得到下面的结论。
Φ(i∗primes[j])=primes[j]∗Φ(i)\Phi(i*primes[j])=primes[j]*\Phi(i)Φ(i∗primes[j])=primes[j]∗Φ(i)
第二种情况:imodprimes[j]!=0第二种情况:i\ mod\ primes[j]!=0第二种情况:i mod primes[j]!=0
因为,primes[j]primes[j]primes[j]不是iii的质因数,但是primes[j]primes[j]primes[j]却是primes[j]∗iprimes[j]*iprimes[j]∗i的质因数。
此时就说明,primes[j]∗iprimes[j]*iprimes[j]∗i的算术基本定理的表达式中比iii的算数基本定理中多了一项primes[j]primes[j]primes[j]
所以,此时Φ(i∗primes[j])\Phi(i*primes[j])Φ(i∗primes[j])比Φ(i)\Phi(i)Φ(i)不仅系数多了一个primes[j]primes[j]primes[j],同时,由于前者的质因数多了一个,所以还多了一项(1−1primes[j])(1-\frac{1}{primes[j]})(1−primes[j]1)
所以:
Φ(i∗primes[j])=primes[j]∗Φ(i)∗(1−1primes[j])=(primes[j]−1)∗Φ(i)\Phi(i*primes[j])=primes[j]*\Phi(i)*(1-\frac{1}{primes[j]})=(primes[j]-1)*\Phi(i)Φ(i∗primes[j])=primes[j]∗Φ(i)∗(1−primes[j]1)=(primes[j]−1)∗Φ(i)
所以根据上面三种情况,我们可以将其融合到我们的欧拉筛中。
代码
#include<iostream>
using namespace std;
const int N=1e6+10;
int primes[N],cnt;
int euler[N];
bool st[N];
void get_eulers(int n)
{euler[1]=1;for(int i=2;i<=n;i++){if(!st[i]){primes[cnt++]=i;euler[i]=i-1;}for(int j=0;primes[j]<=n/i;j++){st[i*primes[j]]=true;if(i%primes[j]==0){euler[i*primes[j]]=primes[j]*euler[i];break;}euler[i*primes[j]]=(primes[j]-1)*euler[i];}}
}
int main()
{int n;cin>>n;get_eulers(n);long long res=0;for(int i=1;i<=n;i++){res+=euler[i];}cout<<res<<endl;return 0;
}