欧拉函数就是指:给定一个n,求得1到n中与n互质的数的个数
再介绍欧拉通项前,首先得介绍唯一分解定理
那么求一个数的欧拉值的公式为:
φ(n)=n * (1-1/P1) * (1-1/P2) * … * (1-1/Pn)
其中的P1到Pn为n分解出来的质因子
那么求一个数的欧拉值的时间复杂度为O(sqrt(n))
代码实现:
int euler(int n)
{
int ans = n;
for(int i = 2;i * i <= n;i++)//标准的分解质因子的模板
{
if(n % i == 0)
{
ans = ans / i * (i-1);
//现在的i为质因子,根据公式(1-(1/i)),也就是乘以(i-1)/i
//而这里先除是因为现在能被整除,避免了误差
while(n % i == 0)
n /= i;
}
}
if(n > 1)
ans = ans / n * (n-1);
return ans;
}
但是如果求1到n中所有数的欧拉值,那么现在的时间复杂度为O(n*sqrt(n)),如果数多还是挺耗时间的。
那么如何优化呢?
首先我们已经知道了每一个数都能写成多个质数的乘积形式。
例:
我们赋值数组phi[16]中phi[1] = 1,phi[2] = 2,…phi[15] = 15
那么我们现在枚举质数:
现在的质数为2,那么我们把2的倍数的数,根据欧拉公式来乘(i-1)/i,也就是phi[2] * = (1/2),phi[4] * = (1/2),phi[6]…phi[14] * = (1/2),然后再枚举3这个质因子,再枚举5…
代码实现
int phi[n+1];
int euler(int n)
{
for(int i = 1;i <= n;i++)
phi[i] = i;
for(int i = 2;i <= Max;i++)//Max就是代表最大值
if(phi[i] == i)//表明了这是一个质数
for(int j = i;j <= Max;j += i)
phi[j] = phi[j]/i*(i-1);
}
这样时间复杂度能降下来
欧拉函数的性质:
1.如果n,m互质,那么 : φ(n*m) = φ(n)*φ(m)
2.如果n为质数,那么 : φ(n) = n-1,可推出1中φ(n * m) = (n-1)*(m-1)
3.如果n % m == 0,那么 : φ(n * m) = m * φ(n)
4.在3的基础上 : if(n % m == 0 && φ(n / m)%m == 0) φ(n) = φ(n/m)*m
5.在3的基础上 : if(n % m == 0 && φ(n / m)%m != 0) φ(n) = φ(n/m)*(m-1)
6.当n为奇数时,φ(n) = φ(2*n)
7.与小于等于n中,与n互质的数之和为:φ(n)*n/2