什么是欧拉函数
定义:在数论,对正整数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本身)。
图源自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]];//利用了欧拉函数是
//积性函数的性质
}
}
}
至此,我们数论的万万万万万万万里长征就开始了一步