定义:欧拉函数表示1-N中与N互质的数的个数;
给定一个数n,求在[1,n]这个范围内两两互质的数的个数
对于这个范围内的每一个数,我们只要找到不超过这个数且与这个数互质的数的个数就可以了
欧拉函数用希腊字母φ表示,φ(N)表示N的欧拉函数.
欧拉函数的简单性质
1.欧拉函数是积性函数(非完全);
积性函数:对于任意互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数。
完全积性函数:对于任意整数a和b有性质f(ab)=f(a)f(b)的数论函数。
2.除了N=2,φ(N)都是偶数;
3.当N为奇数时,φ(2*N)=φ(N);
4.若N是质数p的k次幂,φ(N)=pk-p(k-1)=(p-1)p^(k-1) 因为除了p的倍数之外,其他数都与N互质;
5.当N是质数时,φ(N)=N-1;
若将N表示成质因子分解式
所以我们有
6.φ(N)=N*(1-1/P1)(1-1/P2)…*(1-1/Pn).
求n的欧拉值
首先, 欧拉函数是一个积性函数,当m,n互质时,φ(mn)=φ(m)∗φ(n)
根据唯一分解定理知 n=p1a1∗p2a2∗…∗pxax
因此 φ(n)=φ(p1a1)∗…∗φ(pxax)
对于任意一项 φ(psas)=psas−ps(as−1)
从定义出发 φ(psas)等于小于或等于psas的正整数中与psas互质的数的数目
从1到psas中共有psas个数字
其中与psas不互质的有ps,2ps,…,psas−1∗ps,共psas−1项

所以 φ(psas) = psas - psas−1=psas∗(1−1/ps)
因此
φ(n)=φ(p1^a1^)∗…∗φ(px^ax^)
=(p1^a1^−p1^a1−1^)∗…∗(px^ax^−px^ax−1^)
=p1^a1^∗(1−1/p1)∗p2^a2^∗(1−1/p2)∗…∗px^ax^∗(1−1/px)
=p1^a1^∗p2^a2^∗…∗px^ax^∗(1−1/p1)∗(1−1/p2)∗…∗(1−1/px)
=n∗∏i=1x(1−1/pi)
作者:Sundae
链接:https://www.acwing.com/solution/content/8702/
来源:AcWing
经典例题
AcWing 873. 欧拉函数
给定n个正整数ai,请你求出每个数的欧拉函数。
欧拉函数的定义
1 ~ N 中与 N 互质的数的个数被称为欧拉函数,记为ϕ(N)。
若在算数基本定理中,N=p1a1p2a2…pmam,则:
ϕ(N) = N∗p1−1/p1 ∗ p2−1/p2 ∗ … ∗ pm−1/pm
输入格式
第一行包含整数n。
接下来n行,每行包含一个正整数ai。
输出格式
输出共n行,每行输出一个正整数ai的欧拉函数。
数据范围
1≤n≤100,
1≤ai≤2∗109
输入样例:
3
3
6
8
输出样例:
2
2
4
#include <iostream>
using namespace std;
int phi(int x)//一次性函数
{
int res = x;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)//只有x%i=0才会进
{
res = res / i * (i - 1);
while (x % i == 0) x /= i;//一次性消除全部i
}
if (x > 1) res = res / x * (x - 1);//有没有遗漏
return res;
}
int main()
{
int n;
cin >> n;
while (n -- )
{
int x;
cin >> x;
cout << phi(x) << endl;
}
return 0;
}
AcWing 874. 筛法求欧拉函数
质数ii的欧拉函数即为phi[i] = i - 1:1 ~ i−1均与i互质,共i−1个。
phi[primes[j] * i]分为两种情况:
① i % primes[j] == 0时:primes[j]是i的最小质因子,也是primes[j] * i的最小质因子,因此1 - 1 / primes[j]这一项在phi[i]中计算过了,只需将基数NN修正为primes[j]倍,最终结果为phi[i] * primes[j]。
② i % primes[j] != 0:primes[j]不是i的质因子,只是primes[j] * i的最小质因子,因此不仅需要将基数NN修正为primes[j]倍,还需要补上1 - 1 / primes[j]这一项,因此最终结果phi[i] * (primes[j] - 1)。
作者:番茄酱
链接:https://www.acwing.com/solution/content/3952/
来源:AcWing
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1000010;
int primes[N], cnt;
int euler[N];
bool st[N];
void get_eulers(int n)
{
euler[1] = 1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
primes[cnt ++ ] = i;
euler[i] = i - 1; //1到p-1都和p互质
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0)//p[j]*i的所有质因子都出现在i的所有质因子当中
{
euler[t] = euler[i] * primes[j];//比i的所有质因子多了一个p[j]
break;
}
euler[t] = euler[i] * (primes[j] - 1);
}
}
}
int main()
{
int n;
cin >> n;
get_eulers(n);
LL res = 0;
for (int i = 1; i <= n; i ++ ) res += euler[i];
cout << res << endl;
return 0;
}