欧拉函数用来求 在小于x的正整数且与x互质(公约数只有1)的数的个数,一般用φ(x)表示,这个φ(x)就是欧拉函数,也就是用来解决 “在1-x之间有多少个数与x构成互质关系”的问题
通式:
特别的,φ(1)=1,∏ 是直积符号,表示连乘
其中p1,p2…pi…pn为x的所有质因数,x是一个正整数
证明:
根据唯一分解定理,我们可以把一个整数唯一地分解为多个质数幂次的乘积,即
任取其中一个因数,即t=pk,那么如果将t分解为长度为p的若干段,则能分成pk/p段,也就是p(k-1)段,那么这每一段里,由于p本身是质数,那么将有p-1个数与t互质(因为除了1),所以比t小且与t互质的数就有p(k-1)∗(p-1)这么多,也就是φ(t)=p(k-1)∗(p-1),也是欧拉函数的特殊情况
把这种特殊情况的结论带入求φ(x)中的话,x分解出的每一个piai都可以看成一个ti,然后许多个ti相乘,每个ti都是只有一个质数的幂次的特殊情况,即t1=p1a1,t2=p2a2,那么可以把唯一分解定理的形式写成 x= t1∗t2∗t3∗… ∗tn,也就是
然后对其套用特殊情况的结论进行证明:
由此我们得到且证明了欧拉函数:
常用性质:
有关证明这里不展开了,大部分情况了解就行
-
欧拉函数是积性函数,但不是完全积性函数:
- 积性是指,若当m与n互质时,f(m∗n)=f(m)∗f(n),那么f是积性函数;
- 若对任意正整数,都有f(m∗n)=f(m)∗f(n)成立,则f是完全积性函数;
所以若m,n互质,φ(m∗n)=φ(m)∗φ(n)
-
对于质数p,φ(p)= p-1;
-
若p是质数且t=p(k-1),φ(t)=p(k-1)∗(p-1),也就是证明过程中的特殊情况结论
-
n>2时,φ(x)是偶数;
-
小于n的数中,与n互质的数的总和为:φ(n) * n / 2 (n>1);
-
x的因数(包括1和它自己)的欧拉函数之和等于x,即x=∑d∣x φ(d) ,其中d∣x是x能被d整除的意思。
如何求出欧拉函数:
在以上公式中很显然,需要得知的量就是pi,也就是x的所有质因数,找出比x小的所有质数我们可以用筛法,再加一层判断是否是因数就行了,所以之前学的欧拉筛就可以排上用场了
情况1:如果p为质数且p为x的因数,那么
情况2:如果p不是x的因数,即p,x互质,那么根据积性函数性质
所以代码如下(一定要会写,很有用):
//欧拉筛法求欧拉函数,建议对照欧拉筛法代码一起看
const int N = 1005;
int phi[N];//φ
bool isPrime[N];
int primes[N];
int cnt;
void euler(int n)
{
phi[1] = 1;//1要特判
cnt = 0;
memset(isPrime, 1, sizeof(isPrime));
for (int i = 2; i <= n; i++)//从2开始,i表示已经推到的数的大小,
{
if (isPrime[i] == 1)
{
primes[++cnt] = i;
phi[i] = i - 1;//i是质数则除了1,2-i都是与i互质的
}
for (int j = 1; j <= cnt && primes[j] * i <= n; j++) //prime[j]表示当前推到的质数
{
isPrime[i * primes[j]] = 0;//当前的i*一个质数一定是合数,先把这个合数标记掉
if (i % primes[j] == 0)//此时的primes[j]是从小到大推出的第一个能整除i的质数,也就是primes[j]是i的质因子
{
phi[i * primes[j]] = phi[i] * primes[j];//情况1,若primes[j]是i的质因子,则根据计算公式,i已经包括i*primes[j]的所有质因子
break;//这样能保证每个数只会被自己最小的因子筛掉一次
}
else phi[i * primes[j]] = phi[i] * phi[primes[j]];//情况2,否则两个因子互质了,就可以利用欧拉函数是积性函数的性质
}
}
}