欧拉函数 O ( n ) \,\,\,O(\sqrt{n}) O(n)
1 ∼ N 1∼N 1∼N 中与 N N N 互质的数的个数被称为欧拉函数,记为 ϕ ( N ) ϕ(N) ϕ(N)
两个数互质就是这两个数只有 1 1 1 这个公因子
若在算数基本定理中, N = p 1 a 1 ∗ p 2 a 2 … p m a m N=p_1^{a1}*p_2^{a_2}…p_m^{a_m} N=p1a1∗p2a2…pmam,则:
ϕ ( N ) = N × p 1 − 1 p 1 × p 2 − 1 p 2 × … × p m − 1 p m ϕ(N) = N×\frac{p_1−1}{p_1}×\frac{p_2−1}{p_2}×…×\frac{p_m−1}{p_m} ϕ(N)=N×p1p1−1×p2p2−1×…×pmpm−1
上面这个式子是用容斥原理证明的
模板题:AcWing 873. 欧拉函数
#include<iostream>
#include<vector>
using namespace std;
#define ll long long
int n, a;
int main()
{
scanf("%d", &n);
while(n--)
{
scanf("%d", &a);
int res = a;
for(int i = 2; i <= a/i; ++i)
if(a % i == 0)
{
while(a % i == 0)
a /= i;
res/=i;
res*=i-1;
}
if(a>1)
{
res/=a;
res*=a-1;
}
printf("%d\n", res);
}
return 0;
}
筛法求欧拉函数 O ( n ) \,\,\,O(n) O(n)
解释:
p
h
i
数
组
存
的
是
每
个
数
的
欧
拉
函
数
phi数组存的是每个数的欧拉函数
phi数组存的是每个数的欧拉函数,
p
r
i
m
e
s
数
组
存
的
是
素
数
primes数组存的是素数
primes数组存的是素数
核心内容如下:
①:当
i
i
i 是素数的时候,
p
h
i
[
i
]
=
i
−
1
phi[i]=i-1
phi[i]=i−1
②:当
i
%
p
j
=
=
0
i\%pj==0
i%pj==0 时,因为此时pj是i的质因子,所以
p
h
i
[
p
j
∗
i
]
=
p
j
∗
i
∗
p
1
−
1
p
1
∗
p
2
−
1
p
2
∗
⋅
⋅
⋅
phi[pj*i]=pj*i*\frac{p_1-1}{p_1}*\frac{p_2-1}{p_2}*···
phi[pj∗i]=pj∗i∗p1p1−1∗p2p2−1∗⋅⋅⋅
p
j
pj
pj 后面的就是
p
h
i
[
i
]
phi[i]
phi[i]
所以
p
h
i
[
p
j
∗
i
]
=
p
j
∗
p
h
i
[
i
]
phi[pj*i]=pj*phi[i]
phi[pj∗i]=pj∗phi[i]
③:当
i
%
p
j
!
=
0
i\%pj\,\,!=0
i%pj!=0 时,
p
h
i
[
p
j
∗
i
]
=
p
j
∗
i
∗
p
1
−
1
p
1
∗
p
2
−
1
p
2
∗
⋅
⋅
⋅
∗
p
k
−
1
p
k
∗
p
j
−
1
p
j
phi[pj*i]=pj*i*\frac{p_1-1}{p_1}*\frac{p_2-1}{p_2}*···*\frac{p_k-1}{p_k}*\frac{p_j-1}{p_j}
phi[pj∗i]=pj∗i∗p1p1−1∗p2p2−1∗⋅⋅⋅∗pkpk−1∗pjpj−1
所以
p
h
i
[
p
j
∗
i
]
=
p
j
∗
p
j
−
1
p
j
∗
i
∗
p
1
−
1
p
1
∗
p
2
−
1
p
2
∗
⋅
⋅
⋅
∗
p
k
−
1
p
k
phi[pj*i]=pj*\frac{p_j-1}{p_j}*i*\frac{p_1-1}{p_1}*\frac{p_2-1}{p_2}*···*\frac{p_k-1}{p_k}
phi[pj∗i]=pj∗pjpj−1∗i∗p1p1−1∗p2p2−1∗⋅⋅⋅∗pkpk−1
最后一项是属于
p
j
pj
pj 的
所以
p
h
i
[
p
j
∗
i
]
=
p
h
i
[
p
j
]
∗
p
h
i
[
i
]
phi[pj*i]=phi[pj]*phi[i]
phi[pj∗i]=phi[pj]∗phi[i]
所以
p
h
i
[
p
j
∗
i
]
=
(
p
j
−
1
)
∗
p
h
i
[
i
]
phi[pj*i]=(pj-1)*phi[i]
phi[pj∗i]=(pj−1)∗phi[i]
int primes[MAXN], phi[MAXN], st[MAXN], cnt;
ll n, res;
void get_eulers()
{
phi[1] = 1;
for(int i = 2; i <= n; ++i)
{
if(!st[i])
{
primes[cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0; primes[j] <= n / i; ++j)
{
st[primes[j] * i] = true;
if(i % primes[j] == 0)
{
phi[primes[j] * i] = phi[i] * primes[j];
break;
}
else
phi[primes[j] * i] = phi[i] * (primes[j] - 1);
}
}
}