欧拉函数定理及其性质

欧拉函数就是指:给定一个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

猜你喜欢

转载自blog.csdn.net/moasad/article/details/107175016