欧拉函数
φ
\varphi
φ 的定义,
φ
(
i
)
\varphi(i)
φ(i) 表示从
[
1
,
i
]
[1, i]
[1,i] 之间和
i
i
i 互质的数的数量 (
a
a
a 和
b
b
b 互质即
gcd
(
a
,
b
)
=
1
\gcd(a, b) = 1
gcd(a,b)=1)。欧拉函数是积性函数,例如
a
,
b
a, b
a,b 都为质数,那么
φ
(
a
b
)
=
φ
(
a
)
×
φ
(
b
)
φ(ab) = φ(a) \times φ(b)
φ(ab)=φ(a)×φ(b),递推式为
φ
(
a
b
)
=
φ
(
a
)
×
φ
(
b
)
×
gcd
(
a
,
b
)
φ
(
gcd
(
a
,
b
)
)
φ(ab) = \frac {φ(a) \times φ(b) \times \gcd(a,b)}{φ(\gcd(a,b))}
φ(ab)=φ(gcd(a,b))φ(a)×φ(b)×gcd(a,b)
(证明暂时搁置)
设一个数
N
N
N 可得
N
=
p
1
b
1
×
p
2
b
2
×
p
3
b
3
×
…
×
p
k
b
k
p
为质数
N = p_1^{b_1} \times p_{2}^{b_2} \times p_{3}^{b_3} \times \ldots \times p_{k}^{b_k} \quad p为质数
N=p1b1×p2b2×p3b3×…×pkbkp为质数
因为
KaTeX parse error: Undefined control sequence: \displaylines at position 2: \̲d̲i̲s̲p̲l̲a̲y̲l̲i̲n̲e̲s̲{ \varphi(N) = …
还因为 [ 1 , p b ] [1, p^b] [1,pb] 一共有 p b p^b pb 个数,不和 p b p^b pb 互质的数有 1 × p , 2 × p , 3 × p , … , p b − 1 × p 1 \times p, 2 \times p, 3 \times p, \ldots, p^{b-1} \times p 1×p,2×p,3×p,…,pb−1×p , 总共 p b − 1 p^{b-1} pb−1 个, 剩下的就是满足要求的即 p b − p b − 1 p^b - p^{b-1} pb−pb−1 个数。
即
φ
(
p
b
)
=
p
b
×
(
1
−
1
p
)
φ(p^b) = p^b \times (1 - \frac{1}{p})
φ(pb)=pb×(1−p1)
可得
φ
(
N
)
=
p
1
b
1
×
(
1
−
1
p
1
)
∗
p
2
b
2
∗
(
1
−
1
p
2
)
×
…
p
k
b
k
∗
(
1
−
1
p
k
)
\varphi(N) = p_1^{b_1} \times (1 - \frac{1}{p_1}) * p_2^{b_2} * (1 - \frac{1}{p_2}) \times \ldots p_k^{b_k} * (1 - \frac{1}{p_k})
φ(N)=p1b1×(1−p11)∗p2b2∗(1−p21)×…pkbk∗(1−pk1)
就等于
φ
(
N
)
=
(
p
1
b
1
×
p
2
b
2
×
…
∗
p
k
b
k
)
×
(
1
−
1
p
1
)
∗
(
1
−
1
p
2
)
×
…
×
(
1
−
1
p
k
)
\varphi(N) = (p_1^{b_1} \times p_2^{b_2} \times \ldots * p_k^{b_k}) \times (1 - \frac{1}{p_1}) * (1 - \frac{1}{p_2}) \times \ldots \times (1 - \frac{1}{pk})
φ(N)=(p1b1×p2b2×…∗pkbk)×(1−p11)∗(1−p21)×…×(1−pk1)
又因为
N
=
p
1
b
1
∗
p
2
b
2
∗
.
.
.
∗
p
k
b
k
N = p1^b1 * p2^b2 * ... * pk^bk
N=p1b1∗p2b2∗...∗pkbk
可得
φ
(
N
)
=
N
∗
(
1
−
1
p
1
)
×
(
1
−
1
p
2
)
×
…
×
(
1
−
1
p
k
)
\varphi(N) = N * (1 - \frac{1}{p_1}) \times (1 - \frac{1}{p_2}) \times \ldots \times (1 - \frac{1}{p_k})
φ(N)=N∗(1−p11)×(1−p21)×…×(1−pk1)
就可以通过分解
N
N
N 的质因数求出来
φ
(
N
)
\varphi(N)
φ(N),由此也可以看出,一个数的欧拉函数的大小和质数的次幂无关。
试除法分解质因数是
O
(
n
)
O(\sqrt n)
O(n) 的, 所以求
φ
(
N
)
\varphi(N)
φ(N) 也就是
O
(
n
)
O(\sqrt n)
O(n) 的
具体见代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n, m;
int main()
{
int T;
cin >> T;
while (T -- )
{
cin >> n;
int res = n;
for (int i = 2; i <= n / i; i ++ )
{
if (n % i == 0)
{
res = res / i * (i - 1); // 相当于res * (1 - 1 / i), 这样是为了防止出现小数, 下取整没了, 最主要的就是这里
while (n % i == 0) n /= i;
}
}
if (n != 1) res = res / n * (n - 1); // 这里不要忘记
cout << res << endl;
}
return 0;
}
一个数欧拉函数的大小和质因数的次幂无关
筛法求欧拉函数
O
(
n
)
O(n)
O(n)
这里写的注释很好,就不多重打了。
是用线性筛顺便筛出欧拉函数,首先,线性筛可以筛出质数 p,质数的欧拉函数很好求,因为一个质数在
[
1
,
p
]
[1, p]
[1,p] 中除了 p 本身以外,其他所有数都与它互质,所以
φ
(
p
)
=
p
−
1
\varphi(p) = p - 1
φ(p)=p−1。
而对于筛掉的数,我们可以知道,筛掉的数是用这个数 u 的最小质因子 p 筛去的,唉?质因子是质数吧,按算法运行顺序来说, u 是由
p
×
i
p \times i
p×i 得到的,那么 i 是整数,且肯定比 u 小,按理说,它的欧拉函数我已经求出来了。而
φ
(
p
)
=
p
−
1
\varphi(p) = p - 1
φ(p)=p−1,我们还知道一个等式。
即
φ
(
a
b
)
=
φ
(
a
)
×
φ
(
b
)
×
gcd
(
a
,
b
)
φ
(
gcd
(
a
,
b
)
)
\varphi(ab) = \frac {φ(a) \times φ(b) \times \gcd(a,b)}{φ(\gcd(a,b))}
φ(ab)=φ(gcd(a,b))φ(a)×φ(b)×gcd(a,b)
那么就可以得出来了
φ
(
u
)
=
φ
(
i
×
p
)
=
φ
(
p
)
×
φ
(
i
)
×
gcd
(
p
,
i
)
φ
(
gcd
(
i
,
p
)
)
\varphi(u) = \varphi(i \times p) = \frac {\varphi(p) \times \varphi(i) \times \gcd(p,i)}{\varphi(\gcd(i,p))}
φ(u)=φ(i×p)=φ(gcd(i,p))φ(p)×φ(i)×gcd(p,i)
其中因为
p
p
p 是质数,而
p
<
=
i
p <= i
p<=i ,并且 p 是 i 的质因子,所以
gcd
(
i
,
p
)
=
p
\gcd(i,p) = p
gcd(i,p)=p,所以
φ
(
gcd
(
p
,
i
)
)
=
φ
(
p
)
\varphi(\gcd(p,i)) = \varphi(p)
φ(gcd(p,i))=φ(p)
所以有下式
φ
(
u
)
=
φ
(
i
×
p
)
=
p
×
φ
(
i
)
\varphi(u) = \varphi(i \times p) = {p \times \varphi(i)}
φ(u)=φ(i×p)=p×φ(i)
在注释里还有一种解释方法,这里就不说了。
/*
线性筛可以求出很多附加的东西
具体会在代码里写注释
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1000010;
int n;
int primes[N], cnt;
bool st[N];
int phi[N]; // phi[i] 是i的欧拉函数
LL sum;
int main()
{
cin >> n;
phi[1] = 1; // 1的欧拉函数是1, 需要手动写上
for (int i = 2; i <= n; i ++ )
{
if (st[i] == 0)
{
primes[ ++ cnt] = i;
sum += phi[i] = i - 1; // 首先如果i是质数, 质数和所有数都互质(除了它自己), 那么对于质数i的φ, 就是i - 1
}
for (int j = 1; primes[j] <= n / i; j ++ )
{
st[i * primes[j]] = true;
if (i % primes[j] == 0) // 如果i % pj == 0 那么pj就是i的最小质因数(这点在线性筛里提到过)
{ // 说明i的质因数包括pj, 那么φ(i)里面包括 (1 - 1/pj), 一个数欧拉函数的大小和其质因数的次幂无关, 根据φ(N) = N * (1 - 1/p1) * (1 - 1/p2) * ... * (1 - 1/pk);
sum += phi[i * primes[j]] = phi[i] * primes[j]; // pj * i 比 i 只多了一个pj而且pj还在i的质因数里面, 那么 φ(i*pj)只比φ(i)多一个pj 也就是 φ(i*pj) = φ(i) * pj
break;
}
sum += phi[i * primes[j]] = phi[i] * (primes[j] - 1); // 和上面同理, 但是pj不是i的质因数, 所以φ(i) 不包含 (1 - 1/pj), φ(pj*i)需要加上这个
}
}
cout << sum + 1 << endl;
return 0;
}