对于任意正整数 n n n,欧拉函数 φ ( n ) φ(n) φ(n) 表示小于或等于 n n n 的正整数中,与 n n n 互质的正整数个数。
例如:
对于任意正整数 n n n, φ ( 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),其中, P 1 , P 2 , . . . , P k P_1, P_2, ..., P_k P1,P2,...,Pk 是 n n n 的不同的质因数。
欧拉函数公式,只与因子相关,与指数无关。
例如:
φ ( 10 ) = 10 ∗ ( 1 − 1 2 ) ∗ ( 1 − 1 5 ) = 4 φ(10) = 10 * (1 - \frac{1}{2}) * (1 - \frac{1}{5}) = 4 φ(10)=10∗(1−21)∗(1−51)=4
φ ( 15 ) = 15 ∗ ( 1 − 1 3 ) ∗ ( 1 − 1 5 ) = 8 φ(15) = 15 * (1 - \frac{1}{3}) * (1 - \frac{1}{5}) = 8 φ(15)=15∗(1−31)∗(1−51)=8
利用容斥原理的推导过程:
对数字N进行质因数分解,可得
N = P 1 r 1 ∗ P 2 r 2 ∗ P 3 r 3 ∗ . . . ∗ P k r k N=P_1^{r_1}*P_2^{r_2}*P_3^{r_3}*...*P_k^{r_k} N=P1r1∗P2r2∗P3r3∗...∗Pkrk
由于不能与 N N N 不互质,所以 1 1 1 ~ N N N 不可包含 P 1 , P 2 , . . . , P k P_1,P_2,...,P_k P1,P2,...,Pk 这些质因子。
把 P 1 , P 2 , . . . , P k P_1,P_2,...,P_k P1,P2,...,Pk 的倍数都减去,分别减去 N P 1 , N P 2 , . . . , N P k \frac{N}{P_1},\frac{N}{P_2},...,\frac{N}{P_k} P1N,P2N,...,PkN 个。
但是由于 P 1 , P 2 , . . . , P k P_1,P_2,...,P_k P1,P2,...,Pk 不同质因子的倍数可能会出现重复,有些数重叠的数会被多次减去。如图中重叠部分会被多次相减,因此要补上重叠的数。比如某个数,是 P 2 P_2 P2 的倍数,也是 P 3 P_3 P3 的倍数,就减了两回,还需要再加回来 P 2 ∗ P 3 P_2∗P_3 P2∗P3 的倍数,换做是其他的组合就是 N P 1 ∗ P 2 , N P 1 ∗ P P 3 , . . . , N P 1 ∗ P k , . . \frac{N}{P_1*P_2},\frac{N}{P_1*P_P3},...,\frac{N}{P_1*P_k},.. P1∗P2N,P1∗PP3N,...,P1∗PkN,..
但是更多质因子重叠的部分又会弥补至减去之前的状态,得继续减去。如 P 1 ∗ P 2 ∗ P 3 P_1*P_2*P_3 P1∗P2∗P3这样的更多质因子重叠的部分,而后就像之前一样一减一加最终推出结果。
φ ( 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)
如果 a a a 和 n n n 是正整数,且 a a a 与 n n n 互质,则 a φ ( n ) ≡ 1 ( m o d n ) a^{φ(n)} ≡ 1 (\mod n) aφ(n)≡1(modn)
如果 n n n 为质数,则 a n − 1 ≡ 1 ( m o d n ) a^{n-1} ≡ 1 (\mod n) an−1≡1(modn)
题目描述:
给定 n 个正整数 ai,请你求出每个数的欧拉函数。
输入格式:
第一行包含整数 n。
接下来 n 行,每行包含一个正整数 ai。
输出格式:
输出共 n 行,每行输出一个正整数 ai 的欧拉函数。
数据范围:
1 ≤ n ≤ 100 , 1 ≤ a i ≤ 2 × 1 0 9 1≤n≤100,1≤a_i≤2×10^9 1≤n≤100,1≤ai≤2×109
输入样例:
3
3
6
8
输出样例:
2
2
4
res
对不同的质数只需计算一次,不要将res的计算放到循环中。
res
计算过程中要避免出现小数的情况,将除法提前与大数进行。
#define _CRT_NO_SECURE_WARNINGS
#include
using namespace std;
int phi(int x)
{
int res = x;
for (int i = 2; i <= x / i; ++i)
{
if (x % i) continue;
// res对不同的质数只需计算一次,不要将res的计算放到循环中
res = res / i * (i - 1); // 注意避免出现小数情况
while (x % i == 0) x /= i;
}
if (x > 1) res = res / x * (x - 1);
return res;
}
int main()
{
int n;
cin >> n;
while (n--)
{
int a;
cin >> a;
cout << phi(a) << endl;
}
return 0;
}
题目描述:
给定一个正整数 n n n,求 1 1 1 ~ n n n 中每个数的欧拉函数之和。
输入格式:
共一行,包含一个整数 n n n。
输出格式:
共一行,包含一个整数,表示 1 1 1 ~ n n n 中每个数的欧拉函数之和。
数据范围:
1 < n < 1 0 6 1
输入样例:
6
输出样例:
12
#define _CRT_NO_SECURE_WARNINGS
#include
using namespace std;
const int N = 1e6 + 10;
int phi[N], primes[N], cnt;
bool st[N];
void get_eulers(int n)
{
for (int i = 2; i <= n; ++i)
{
phi[1] = 1;
if (!st[i])
{
phi[i] = i - 1;
primes[cnt++] = i;
}
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;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1);
}
}
}
int main()
{
int n, res = 0;
cin >> n;
get_eulers(n);
for (int i = 1; i <= n; ++i) res += phi[i];
cout << res << endl;
return 0;
}