欧拉函数的代码实现

欧拉定理证明出门左转

线性筛素数出门直走

单个筛欧拉函数由欧拉函数公式直接在给n分解质因数时连乘就好

代码

int phi(int 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;  
}  

先说一个近似线性筛的筛法

void Euler()
{
    phi[1]=1;
    for(int i=2;i

线性筛欧拉函数建立在线性筛素数的基础之上

重要性质:若i%p=0,p是素数,那么φ(i*p)=φ(i)*p,若i%p!=0,p是素数,那么φ(i*p)=φ(i)*(p-1)

证明(该证明可能存在错误):当i%p=0时,若GCD(a,b)=1,则GCD(a+b,b)=1,由此可以得出,将φ(i)中的数每个加i,则会得到另外φ(i)个数,若以此类推,累加(p-1)次,则一共有p*φ(i)个数与i互质,因为p是i的质因子,所以与i互质的数必定与i*p互质,所以φ(i*p)=φ(i)*p;当i%p!=0时,发现i,p互质,且p为素数,所以φ(p)等于p-1,由积性函数性质可得φ(i*p)=φ(i)*φ(p)=φ(i)*(p-1)

代码

void getphi()    
{    
   int vis[M],phi[M],pri[M],tot;   
   for(int i=2;i<=n;i++)   
   {    
     	if(!vis[i])//先判断i是不是素数    
    	{    
            pri[++tot]=i; 
            phi[i]=i-1;//当 i 是素数时小于i的所有大于零的数都和i互素    
        }    
       	for(int k=1;k<=tot;k++)    
       	{    
          	if(i*pri[k]>M)  break;    
          	vis[i*pri[k]]=1;//按照筛素数,筛掉i的倍数 
          	if(i%pri[k]==0)//如果有一个质数是i的因子,那么phi(i*pri[k])=phi(i)*pri[k]  
          	{    
             	phi[i*pri[k]]=phi[i]*pri[k];break;    
          	}    
          	else  phi[i*pri[k]]=phi[i]*(phi[pri[k]]);
			  //利用了欧拉函数的积性,两个数互质,那么phi(i*k)=phi(i)*phi(pri[k])   
       	}    
   }    
}    



你可能感兴趣的:(数论&&组合数学)