目录
欧拉函数的定义
对于正整数 \(n\),欧拉函数 \(\varphi(n)\) 是小于等于 \(n\) 的正整数中与 \(n\) 互质的数的个数。
若有标准分解 \(n = p_1^{k_1} p_2^{k_2} \cdots p_r^{k_r}\)(其中 \(p_i\) 为互异的质因子,各 \(k_i \ge 1\) 为质因子的次数),则欧拉函数在该处的值为
\[\varphi(n) = p_1^{k_1-1} p_2^{k_2-1} \cdots p_r^{k_r-1} (p_1-1) (p_2-1) \cdots (p_r-1) \]亦可等价写成
\[\varphi(n) = n (1 - \frac{1}{p_1}) (1 - \frac{1}{p_2}) \cdots (1 - \frac{1}{p_r}) \]即
\[\varphi(n) = n \prod_{i=1}^r (1 - \frac{1}{p_i}) \]对应的 C++ 实现代码如下:
int phi(int n) {
int res = n;
for (int i = 2; i*i <= n; i++) {
if (n % i == 0)
res = res / i * (i-1);
while (n % i == 0)
n /= i;
}
if (n > 1) res = res / n * (n-1);
return res;
}
欧拉函数的一般解法(试除法)
《例题1.欧拉函数基础1》:https://www.luogu.com.cn/problem/U271793
示例程序:
#include <bits/stdc++.h>
using namespace std;
int phi(int n) {
int res = n;
for (int i = 2; i*i <= n; i++) {
if (n % i == 0)
res = res / i * (i-1);
while (n % i == 0)
n /= i;
}
if (n > 1) res = res / n * (n-1);
return res;
}
int main() {
int t, n;
cin >> t;
while (t--) {
cin >> n;
cout << phi(n) << endl;
}
return 0;
}
线性筛
线性筛的主要思想我觉得就是一句话:
对于一个合数,使用它最小的质因子去过滤掉它(这里,过滤的意思就是排除它是质数的可能)。
《P3383 线性筛素数》:https://www.luogu.com.cn/problem/P3383
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxp = 1e8 + 5, maxn = 6e6 + 5;
bool isp[maxp];
int prime[maxn], cnt;
void init(int n) {
for (int i = 2; i <= n; i++) {
if (!isp[i])
prime[cnt++] = i;
for (int j = 0; j < cnt && i * prime[j] <= n; j++) {
isp[i * prime[j]] = true;
if (i % prime[j] == 0)
break;
}
}
}
int n, q, k;
int main() {
scanf("%d%d", &n, &q);
init(n);
while (q--) {
scanf("%d", &k);
printf("%d\n", prime[k-1]);
}
return 0;
}
欧拉函数的线性筛法
《例题2.欧拉函数基础2》:https://www.luogu.com.cn/problem/U271924
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7 + 5;
bool isp[maxn];
int phi[maxn], prime[maxn], cnt;
void init(int n) {
phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (!isp[i]) {
prime[cnt++] = i;
phi[i] = i-1;
}
for (int j = 0; j < cnt && i * prime[j] <= n; j++) {
isp[i * prime[j]] = true;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int main() {
init(maxn-1);
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
printf("%d\n", phi[n]);
}
return 0;
}