AcWing 873.欧拉函数
题目描述
给定n个正整数αi,请你求出每个数的欧拉函数
欧拉函数定义
1~N中与N互质的数的个数被称为欧拉函数,记为Φ(N)。
互质是公约数只有1的两个整数,叫做互质整数。
eg:求Φ(6),和6只有公约数为1的数有1和5,一共两个数,所以Φ(6) = 2
p1 到 pk 是N的质因子
若在算数基本定理中,有
N=p1α1∗p2α2∗...∗pkαkN = 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−Np1−Np2−...−Npks = N - \frac {N} {p_1} - \frac {N} {p_2} -...- \frac {N} {p_k}s=N−p1N−p2N−...−pkN
2、加上所有pi * pj的倍数
s=N−Np1−Np2−...−Npk+Np1p2+Np1p3+...+Npipjs = 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−Np1−Np2−...−Npk+Np1p2+Np1p3+...+Npipj−Np1p2p3−Np1p2p4−...−Npipjpks = 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−1p1)∗(1−1p2)∗...∗(1−1pk)Φ(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;
}