什么是歐拉函數
歐拉函數是小於x的整數中與x互質的數的個數,特殊的 φ(1) = 1.
如何計算歐拉函數

其中p1,p2,.....pn為x的所有質因數,x是正整數。
歐拉函數的幾個性質
1、對於質數p φ(p)=p-1.
2、若p為質數,n = pk,則 φ(n) = pk - pk-1
3、歐拉函數是積性函數,但不是完全積性函數(不互質也滿足等式)。若m,n互質,則φ(m*n)=φ(m)*φ(n).
4、當n>2時,φ(n)* n / 2 (n > 1).
5、小於n且與n互質的數的總和為:φ(n)* n / 2 (n > 1).
6.n = ∑d∣n φ(d),即n的因數(包括1和它自己)的歐拉函數之和等於n
求歐拉函數
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)//確保i為n的質因數
{
n /= i ;
}
}
}
if(n > 1) ans -= ans/n ;//最后可能還剩下一個質因數沒有除,例如10的歐拉函數
return ans ;
}
2、埃拉托斯特尼篩求歐拉函數
void euler(int n)//求1-n的歐拉函數
{
for(int i = 2 ; i <= n ; i++) phi[i] = i ;
for(int i = 2 ; i*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)//求1-n的歐拉函數
{
memset(vis , true , sizeof(vis));
int cnt = 0 ;
for(int i = 2 ; i <= n ; i++)
{
if(vis[i])
{
prime[cnt++] = i ;
phi[i] = i - 1 ;
}
for(int j = 0 ; j < cnt && prime[j] * i <= n ; j++)
{
vis[i*prime[j]] = 0 ;
if(i % prime[j] == 0)//保證每一個數都被它最小質因數篩去
{
phi[i*prime[j]] = phi[i] * prime[j] ;
break ;
}
else{
phi[i*prime[j]] = phi[i] * phi[prime[j]];//i與prime[j]互質可以根據歐拉函數的積性函數性質求
}
}
}
}
參考博客https://blog.csdn.net/liuzibujian/article/details/81086324
