2021-03-06

这篇博客探讨了一种解决数组中是否存在一个数与其他所有数互质问题的高效算法。通过分解质因数并统计每个质因数的个数,避免了O(N*N*logN)的复杂度,实现了更快速的判断。文章详细介绍了如何遍历数组,检查每个数的质因数,并使用哈希映射来存储和比较质因数信息,最终确定数组是否包含互质数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接
本题主要是对数组中是否存在一个数与其他所有数互质的判断
枚举求最大公约数时间复杂度是O(N * N * logN)会超时。
解法:对每个数分解质因数,记录数组中每个质因数的个数之和,再用一个数组存每个质因数在某个数中出现的次数
再次遍历数组中的每一个数,若这个数有这个质因数且数组中的质因数个数 > 该数的质因数个数,说明数组中的另一个数存在该质因数,即存在一个数与这个数不互质。

#include <iostream>
#include <cstring>
#include <vector>
#include <unordered_map>
#include <cstdio>
#include <cstdlib>

using namespace std;

const int N = 1000010, M = 100;

int primes[N], n, m, a[N], cnt;
bool st[N];
int mind[N];
unordered_map<int, int> whole;

int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}

void make_primes(int n) {
    for (int i = 2; i < n; i ++) {
        if (!st[i]) primes[cnt ++] = i;
        for (int j = 0; primes[j] <= n / i; j ++) {
            st[primes[j] * i] = 1;
            if (i % primes[j] == 0) break;
        }
    }
}

bool pairwise() {
    for (int i = 0; i < n; i ++) {
        int t = a[i];
        for (int j = 2; j <= t / j; j ++) {	//分解质因数
            if (t % j == 0) {
                int s = 0;
                while (t % j == 0) s ++, t/= j;
                whole[j] += s;
                mind[j] = min(mind[j], s);
            }
        }
        if (t > 1)  whole[t] += 1, mind[t] = min(mind[t], 1);
    }

    for (int i = 0; i < cnt; i ++) {	//判断相同的质因数是否全部来自同一个数
        int p = primes[i];
        if (mind[p] < whole[p]) return false;
    }
    return true;
}

bool setwise() {
    int x = a[0];
    for (int i = 0; i < n; i ++)    {
        x = gcd(x, a[i]);
        if (x == 1) return true;
    }
    return false;
}
int main() {
    memset(mind, 0x3f, sizeof mind);
    cin >> n;
    make_primes(N);
    for (int i = 0; i < n; i ++)
        cin >> a[i];

    if (pairwise ()) {
        cout << "pairwise coprime";
    }
    else {
        if (setwise()) cout << "setwise coprime";
        else cout << "not coprime";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值