欧拉函数的实现

欧拉函数的定义

对于正整数 \(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;
}

参考资料

posted @ 2023-01-01 14:15  quanjun  阅读(121)  评论(0)    收藏  举报