📜  范围 [L, R] 内所有可能的互质不同元素对(1)

📅  最后修改于: 2023-12-03 15:27:47.026000             🧑  作者: Mango

计算范围 [L, R] 内所有可能的互质不同元素对

本文介绍如何计算在范围 [L, R] 内所有可能的互质不同元素对。

什么是互质不同元素对

两个正整数 a 和 b,如果它们的最大公约数为 1,即 gcd(a, b) = 1,则称这两个数是互质的。互质的两个数成为“互质数对”或“互质不同元素对”。

如何计算

计算范围 [L, R] 内所有可能的互质不同元素对,可以枚举所有的数对 (i, j),其中 i 属于 [L, R],j 属于 [i+1, R],然后通过判断它们是否互质来确定它们是否构成互质不同元素对。

以下是 C++ 代码实现:

vector<pair<int, int>> get_coprime_pairs(int L, int R) {
    vector<pair<int, int>> res;
    for (int i = L; i <= R; i++) {
        for (int j = i + 1; j <= R; j++) {
            if (gcd(i, j) == 1) {
                res.emplace_back(i, j);
            }
        }
    }
    return res; 
}
性能优化

上述方法虽然可行,但它的时间复杂度为 O((R-L)^2),对于范围较大的数据会很慢。我们可以通过以下几个方法来优化:

1. 从小到大枚举质数

在枚举数对时,我们只需要枚举 L 和 R 之间的质数,因为不是质数的数肯定可以被分解成小于它本身的两个数的积,也就不可能与任何一个大于它的数构成互质不同元素对。

以下是 C++ 代码实现:

vector<pair<int, int>> get_coprime_pairs(int L, int R) {
    vector<int> primes = get_primes(R);
    vector<pair<int, int>> res;
    for (int p : primes) {
        if (p < L) continue;
        for (int i = p + 1; i <= R; i++) {
            if (gcd(i, p) == 1) {
                res.emplace_back(i, p);
            }
        }
    }
    return res;
}
2. 利用欧拉函数

欧拉函数 phi(n) 表示小于等于 n 的正整数中与 n 互质的数的个数,可以用以下公式计算:

phi(n) = n * (1 - 1/p1) * (1 - 1/p2) * ... * (1 - 1/pk)

其中 p1, p2, ..., pk 是 n 的质因数。因此,如果我们已经计算出小于等于 R 的所有质数及它们的指数,就可以利用欧拉函数快速计算出在范围 [L, R] 内每个数与小于等于 R 的所有质数都互质的数的个数,然后根据这些个数构造出所有互质不同元素对。

以下是 C++ 代码实现:

vector<pair<int, int>> get_coprime_pairs(int L, int R) {
    vector<int> primes, phi;
    get_primes_and_phi(R, primes, phi);
    vector<pair<int, int>> res;
    for (int i = L; i <= R; i++) {
        for (int j = 0; j < primes.size() && primes[j] < i; j++) {
            int k = i / primes[j] * phi[primes[j]];
            if (k >= primes[j] && k < i && gcd(i, k) == 1) {
                res.emplace_back(i, k);
            }
        }
    }
    return res;
}
3. 利用完全积性函数

如果 f(n) 是完全积性函数,且 f(n) = f(p^k) 只与 p 相关,那么对于任意正整数 m 和 n,如果 gcd(m, n) = 1,则有 f(mn) = f(m) * f(n)。

因此,我们可以先计算出所有小于等于 R 的质数及它们的指数,并计算出在 [L, R] 范围内每个质数在多少个不同的数对中出现,然后再根据完全积性函数的性质计算出所有的互质不同元素对。

以下是 C++ 代码实现:

vector<pair<int, int>> get_coprime_pairs(int L, int R) {
    vector<int> primes, exp, cnt;
    get_primes_and_exp(R, primes, exp);
    cnt.assign(R + 1, 0);
    for (int p : primes) {
        for (int k = 1; k * p <= R; k++) {
            cnt[p * k - L]++;
        }
    }
    vector<pair<int, int>> res;
    for (int i = L; i <= R; i++) {
        int c = cnt[i - L];
        if (c == 0 || (c == 1 && exp[i] > 0)) continue;
        res.reserve(res.size() + c - exp[i]);
        for (int j = 0; primes[j] < i && j < primes.size(); j++) {
            int k = i / primes[j];
            while (k % primes[j] == 0) {
                k /= primes[j];
            }
            if (k > 1 && k < i && gcd(i, k) == 1) {
                res.emplace_back(i, k);
            }
        }
    }
    return res;
}
总结

本文介绍了如何计算范围 [L, R] 内所有可能的互质不同元素对,并提出了三种优化方法,使得计算效率更高。了解互质不同元素对的概念和计算方法对理解和分析算法中数论问题的解法有重要意义。