AcWing 873.欧拉函数
题目描述
给定n个正整数αi,请你求出每个数的欧拉函数
欧拉函数定义
1~N中与N互质的数的个数被称为欧拉函数,记为Φ(N)。
互质是公约数只有1的两个整数,叫做互质整数。
eg:求Φ(6),和6只有公约数为1的数有1和5,一共两个数,所以Φ(6) = 2
p1 到 pk 是N的质因子
若在算数基本定理中,有
N
=
p
1
α
1
∗
p
2
α
2
∗
.
.
.
∗
p
k
α
k
N = p_1^{α1} * p_2^{α2} * ... * p_k^{αk}
N=p1α1∗p2α2∗...∗pkαk
证明欧拉函数(使用容斥原理):
首先我们假设N的所有质因数是p1到pk,求1 ~N-1中与N互斥的数的个数s
1、从1 ~ N中去掉p1p2…pk的所有倍数
s
=
N
−
N
p
1
−
N
p
2
−
.
.
.
−
N
p
k
s = N - \frac {N} {p_1} - \frac {N} {p_2} -...- \frac {N} {p_k}
s=N−p1N−p2N−...−pkN
2、加上所有pi * pj的倍数
s
=
N
−
N
p
1
−
N
p
2
−
.
.
.
−
N
p
k
+
N
p
1
p
2
+
N
p
1
p
3
+
.
.
.
+
N
p
i
p
j
s = N - \frac {N} {p_1} - \frac {N} {p_2} -...- \frac {N} {p_k} + \frac {N} {p_1 p_2} + \frac {N} {p_1 p_3} + ...+ \frac {N} {p_i p_j}
s=N−p1N−p2N−...−pkN+p1p2N+p1p3N+...+pipjN
3、减去所有pi * pj * pk 的倍数
s
=
N
−
N
p
1
−
N
p
2
−
.
.
.
−
N
p
k
+
N
p
1
p
2
+
N
p
1
p
3
+
.
.
.
+
N
p
i
p
j
−
N
p
1
p
2
p
3
−
N
p
1
p
2
p
4
−
.
.
.
−
N
p
i
p
j
p
k
s = N - \frac {N} {p_1} - \frac {N} {p_2} -...- \frac {N} {p_k} + \frac {N} {p_1 p_2} + \frac {N} {p_1 p_3} + ...+ \frac {N} {p_i p_j}- \frac {N} {p_1p_2p_3} - \frac {N} {p_1p_2p_4} -...- \frac {N} {p_ip_jp_k}
s=N−p1N−p2N−...−pkN+p1p2N+p1p3N+...+pipjN−p1p2p3N−p1p2p4N−...−pipjpkN
4、以此类推…。
5、最后求出欧拉函数的核心公式(最重要):
Φ
(
N
)
=
N
∗
(
1
−
1
p
1
)
∗
(
1
−
1
p
2
)
∗
.
.
.
∗
(
1
−
1
p
k
)
Φ(N) = N *(1-\frac {1} {p_1}) * (1-\frac {1} {p_2}) * ... *(1-\frac {1} {p_k})
Φ(N)=N∗(1−p11)∗(1−p21)∗...∗(1−pk1)
输入格式
第一行包含整数n。
接下来n行,每行包含一个正整数αi。
输出格式
输出共n行,每行输出一个正整数αi的欧拉函数。
数据范围
1 ≤ n ≤ 100,
1 ≤ αi ≤ 2 * 109
输入样式:
3
3
6
8
输出样式:
2
2
4
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll; // 数据范围较大记得用long long
const int N = 110;
int n;
int main()
{
cin >> n;
while(n--)
{
int cnt = 0;
ll primes[N];
int x;
cin >> x;
ll ans = x;
// 先分解质因数
for(int i = 2 ; i <= x / i ; i ++ )
{
if(x % i == 0)
{
ans = ans / i * (i - 1); // ans = ans * (1 - 1 / x),需要化简,结果就是ans = ans / i * (i - 1)
while(x % i == 0) x /= i;
}
}
if(x > 1) ans = ans / x * (x - 1); // 最后一个比较大的质因子x
cout << ans << endl;
}
return 0;
}