【问题标题】:Maximum sub-arrays that an array can be divided into such that GCD of any two elements in different sub-arrays is always 1?一个数组可以划分的最大子数组,使得不同子数组中任意两个元素的 GCD 始终为 1?
【发布时间】:2017-08-22 20:35:33
【问题描述】:

给定n,数组元素的数量和arr[n],数字数组,需要找到数组可以划分的最大子数组数,使得GCD(a,b)=1对于每个@987654325 @ 和b 属于不同的子数组。

例如:

5
2 3 4 5 6
Ans: 2 ----> {(2,3,4,6),(5)}

任何其他进一步划分它的尝试都不会满足条件。

我的方法:
1. 对数组进行排序。
2. 继续计算元素的lcm
3.每次元素的gcd和之前元素的lcm1时,增加计数器。

int main()
{
        int n;
        cin>>n;
        long long int arr[n];
        for(int i=0;i<n;++i)
            cin>>arr[i];
        sort(arr,arr+n);
        long long int ans=1,l=arr[n-1];
        for(int i=n-2;i>=0;i--)
        {
            if(gcd(l,arr[i])==1)
                ans++;
            l=lcm(l,arr[i]);
        }
        cout<<ans<<endl;
    return 0;
} 

在我的答案被wrong answer 多次判断后,我很困惑我的解决方案是否正确。由于n 的限制是10^6 并且数组元素是10^7,解决方案失败的另一个原因是LCM 可以超过long long 限制。有没有其他可能的解决方案?还是目前的做法有什么错误?

【问题讨论】:

  • 你指的是这个问题吗:codechef.com/problems/CHEFGRUP 因为约束声明 2 1。
  • @Shubham .. 是的,它是一样的......我只是举了一个例子......编辑!

标签: c++ arrays algorithm


【解决方案1】:

我认为这是您所指的问题:https://www.codechef.com/problems/CHEFGRUP

我的做法如下(我超过了时间限制)

Step - 1:计算 [1, 10^7] 范围内的所有素数。

这可以使用埃拉托色尼筛法完成,复杂度为 O(nlog(log(n)),其中 n 最高可达 10^7

步骤 - 2:使用上面计算的素数向量来找到数组中所有数字的素数分解。

一旦我们拥有所有必需的素数,这可以非常有效地实现。

这一步要注意的一点是,假设我们有 2 个数的素数分解包含共同的素数,那么这两个元素不能在不同的子数组中,因为 GCD 不会为 1(如问题所要求的那样) .因此,对于所有这样的对,它们必须在同一个子数组中。如何做到这一点?

步骤 - 3:使用不相交集数据结构。

我们可以创建所有素数的不相交集。所以一开始的集合数将是素数的个数。然后,在每次因式分解过程中,我们将连接所有作为除数的素数,并将它们与原始数加在同一组中。这将对所有数字重复。

此外,我们必须检查一次,是否首先需要一些素数。因为在这一步之前,我们只是假设有与范围内的素数一样多的集合。但有些可能没有使用。因此,可以通过遍历一次循环并找到唯一代表的数量来检查这一点。这将是我们的答案。

我的代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;

int prime[(int)1e7+10] = {0};

struct union_find {
    std::vector <int> parent, rank;

    // Constructor to initialse 'parent' and 'rank' vector.
    union_find(int n) {
        parent = std::vector <int> (n);
        rank = std::vector <int> (n, 0);        // initialse rank vector with 0.
        for(int i = 0; i < n; i++)
            parent[i] = i;
    }

    // Find with Path Compression Heuristic.
    int find_(int a) {
        if(a == parent[a])
            return a;
        return parent[a] = find_(parent[a]);
    }

    // Union by checking rank to keep the depth of the tree as shallow as possible.
    void union_(int a, int b) {
        int aa = find_(a), bb = find_(b);
        if(rank[aa] < rank[bb])
            parent[aa] = bb;
        else
            parent[bb] = aa;
        if(rank[aa] == rank[bb])
            ++rank[aa];
    }
};

union_find ds(1e7+10);

int main() {
    int n;
    int sq = sqrt(1e7+10);
    for(int i = 4; i < 1e7+10; i += 2)
        prime[i] = 1;
    for(int i = 3; i <= sq; i += 2) {
        if(!prime[i]) {
            for(int j = i*i; j < 1e7+10; j += i)
                prime[j] = 1;
        }
    }

    vector <int> primes;
    primes.push_back(2);
    for(int i = 3; i < 1e7+10; i += 2) {
        if(!prime[i])
            primes.push_back(i);
    }


    scanf("%d", &n);
    int a[n];
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }

    for(int i = 0; i < n; i++) {

        int temp = a[i];
        // int sq = sqrt(temp);
        vector <int> divisors;
        for(int j = 0; j < primes.size(); j++) {
            if(primes[j] > temp)
                break;
            if(temp % primes[j] == 0) {
                divisors.push_back(primes[j]);
                while(temp % primes[j] == 0) {
                    temp /= primes[j];
                }
            }
        }
        if(temp > 2)
            divisors.push_back(temp);

        for(int i = 1; i < divisors.size(); i++)
            ds.union_(divisors[i], divisors[i-1]);
        if(divisors.size() > 0)
            ds.union_(divisors[0], a[i]);
    }

    set <int> unique;
    for(int i = 0; i < n; i++) {
        int x = ds.find_(a[i]);
        unique.insert(x);
    }

    printf("%d\n", unique.size());
    return 0;
}

【讨论】:

  • 因式分解和 union_find 是一个很好的方法,但是要分解数字
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 2011-08-19
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
相关资源
最近更新 更多