欧拉函数和求解和两种筛法打表详讲

什么是欧拉函数

定义:在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)。

欧拉函数的通式:φ(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本身)。

欧拉函数和求解和两种筛法打表详讲_第1张图片
图源自liuzibujian大佬,错误已经更正
证明见链接https://www.cnblogs.com/henry-1202/p/10246196.html#_label4,,甚至是中学生大佬OTZ

求解

单个数字求法

int euler(int n)  
{  
    int ans=n;  
    for(int i=2;i*i<=n;i++){  
        if(n%i==0){  
            ans-=ans/i;  //通项公式  n*(1-1/pi)。。。
            while(n%i==0){  //保证是素因子
                n/=i;  
            }  
        }  
    }  
    if(n>1)ans-=ans/n;  //排除还可能存在的素因子,如果还存在,只能有一个
    					//因为一个数一定被分解成几个质数的乘积,超过sqrt(这个数)
    					//只能有一个这样的质数
    					//至于为什么可以分解,用短除法理解或者百度唯一分解定理
    return ans;  
}

埃氏筛求欧拉函数

原理就是通项公式,n*(1-1/pi)。。。。变成n*(pi-1)/pi。。。。。

不懂埃氏筛的可以翻翻我的素数筛https://blog.csdn.net/weixin_43879181/article/details/95444651

void euler(int n)
{
    for (int i=1;i<=n;i++) phi[i]=i;//先全是质数,不懂的去先看素数筛,
    								//上面链接
    for (int i=2;i<=n;i++)
    {
        if (phi[i]==i)//这代表i是质数
        {
            for (int j=i;j<=n;j+=i)
            {
                phi[j]=phi[j]/i*(i-1);//把i的倍数更新掉
            }
        }
    }
}

欧拉筛求欧拉函数

同样的不懂欧拉筛的去看我的线性筛的博客,还有什么问题欢迎评论写出

void euler(int n)
{
	phi[1]=1;//1要特判 
	for (int i=2;i<=n;i++)
	{
		if (flag[i]==0)//这代表i是质数 
		{
			prime[++num]=i;
			phi[i]=i-1;
		}
		for (int j=1;j<=num&&prime[j]*i<=n;j++)//经典的欧拉筛写法 
		{
			flag[i*prime[j]]=1;//先把这个合数标记掉 
			if (i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];//若prime[j]是i的质因子,
												//则根据计算公式,i已经包括
												//i*prime[j]的所有质因子 
				break;//经典欧拉筛的核心语句,
				       //这样能保证每个数只会被自己最小的因子筛掉一次 
			}
			else phi[i*prime[j]]=phi[i]*phi[prime[j]];//利用了欧拉函数是
			                                          //积性函数的性质 
		}
	}
}

至此,我们数论的万万万万万万万里长征就开始了一步

你可能感兴趣的:(欧拉定理,数论,ACM集训)