【数论基础】- 欧拉函数

什么是欧拉函数

定义:
在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)。此函数以其首名研究者欧拉命名(Euler’s totient function),它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。
通式:
欧拉函数的通式:φ(n)=n*(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/p4)……(1-1/pn),其中p1, p2……pn为n的所有质因数,n是不为0的整数。φ(1)=1(唯一和1互质的数就是1本身)。
求解板子:

int euler(int n)  
{  
    int ans=n;  
    for(int i=2;i*i<=n;i++){  
        if(n%i==0){  
            ans-=ans/i;  
            while(n%i==0){  
                n/=i;  
            }  
        }  
    }  
    if(n>1)ans-=ans/n;  
    return ans;  
}

不懂的疑点分析:
1.代码中的 ans-=ans/i; 这一步就是对应欧拉函数的通式。
2.while(n%i==0) n/=i; 这一个语句是为了保证完全消除我们刚才得到的那个i因子。确保我们下一个得到的i是n的素因子。因为质数是不会再有除1和本身之外的因子的。
3.if(n>1)ans-=ans/n; 这个语句是为了保证我们已经除完了n的所有的素因子,有可能还会出现一个我们未除的因子,如果结尾出现n>1 ,说明我们还剩一个素因子未除,这个不好理解。举个例子:当n=10,我们第一个循环只跑到了3,然而他5这一个因子并没有筛选出来,所以这个if就是避免这种情况的发生。

打表法:
上面的方法求单个数据很实用,但是对于一道题,多次让你计算欧拉函数的值,不如采用打表的方式存下每个数的欧拉函数值E(x)。下面我给出板子。

打表板子:

void euler()  
{  
    E[1]=1;  
    for(int i=2;i<maxn;i++)  
        E[i]=i;  
    for(int i=2;i<maxn;i++){  
        if(E[i]==i)  
        for(int j=i;j<maxn;j+=i){  
            E[j]=E[j]/i*(i-1);  
        }
    }  
}

这个方法优化的地方在于,每次遍历到一个数的时候,会对他所有的倍数进行处理,即我们每次处理都可以只遍历到质数,再有这个质数去更新他们公倍数的值。

例如:我们处理2的时候,从2开始循环,每次加2,改变2的倍数的E的值,而由于值的改变,我们下一次外层循环将不再单独处理2的倍数的值。但是,要注意的是,这样只是消除了2这一个质因子。
例如6,我们在处理2的时候,他的值变成了3,但是在对3进行处理时还会更新一次,因为3也是他的质因子,最终使得E(6)=2。

特别提醒:
对于E(1),有些题目要求他为0,而百度百科等权威上规定的是1,这点很坑。。。要特别注意。

发布了43 篇原创文章 · 获赞 56 · 访问量 5110

猜你喜欢

转载自blog.csdn.net/tran_sient/article/details/95206152