关于欧拉函数

欧拉函数,
对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目。

这是我在ACM队内训练赛的时候遇到的一个函数,其实最初是在离散数学课本上了解到了这个函数,但是当时并没有留下太深的印象,现在总结一下。
首先要知道欧拉函数的公式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn)
其中p1,p2,p3是x的所有质因子。

1.第一种算法:
直接求法:
暴力遍历x的所有质因子直接求解:

int euler(int n){ //返回euler(n)   
     int res=n,a=n;  
     for(int i=2;i*i<=a;i++){  
         if(a%i==0){  
             res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出   
             while(a%i==0) a/=i;  
         }  
     }  
     if(a>1) res=res/a*(a-1);  
     return res;  
}

其中while(a%i==0) a/=i; 是在进行保证可以整除的是素数的过程。
另外,for(int i=2;i*i<=a;i++)也利用了素数筛选法的思想。

2.第二种算法:
筛选法打表求欧拉函数

#define Max 1000001  
int euler[Max];  
void Init(){   
     euler[1]=1;  
     for(int i=2;i<Max;i++)  
       euler[i]=i;  
     for(int i=2;i<Max;i++)  
        if(euler[i]==i)  
           for(int j=i;j<Max;j+=i)  
              euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出   
}  

打表求值,不断求得。

2017-06-26 17:43:32 星期一 更新
今天在《算法竞赛入门(第二版)》(紫书)上看到了一种利用类似与素数筛选法的方法直接求由1~n的所有欧拉函数值的办法。
给出代码:

int pi[50001+10];
const int maxn=50001;
int euler(int n)
{
    memset(pi,0,sizeof(pi));
    pi[1]=1;
    for(int i=2;i<=n;i++)
        if(!pi[i])
    {
        for(int j=i;j<=n;j+=i)
        {
            if(!pi[j])
                pi[j]=j;
            pi[j]=pi[j]/i*(i-1);
        }
    }
}

利用这个办法可以在nloglogn的复杂度内求得由1到n的所有欧拉函数值。

2017-08-09  12:48:12

新增一些欧拉函数的性质:

1.如果一个数x是素数,则该数的欧拉函数值为x-1。

2.若m,n互质,

 
3.当n为奇数时,
 
posted @ 2017-07-27 15:48  DLKKILL  阅读(258)  评论(0编辑  收藏  举报