给定n
,数组元素的数量和arr[n]
(数字数组),需要找到数组可以分成的最大子数组,以便{{1对于属于不同子阵列的每个GCD(a,b)=1
和a
。
例如:
b
每一次进一步分裂的尝试都不符合条件。
我的方法:
1.对阵列进行排序
2.继续计算元素的5
2 3 4 5 6
Ans: 2 ----> {(2,3,4,6),(5)}
3.每次元素的lcm
和之前元素的gcd
为lcm
时,都会增加计数器。
1
在多次判断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
限制。还有其他解决方案吗?或者目前的方法有什么错误吗?
答案 0 :(得分:1)
我认为这是您所指的问题:https://www.codechef.com/problems/CHEFGRUP
我的方法如下(我超时限制):
这可以使用Sieve of Eratosthenes完成,复杂性为O(nlog(log(n))
,其中n可以高达10^7
。
一旦我们拥有所有必需的素数,这可以非常有效地实现。
在这一步中要注意的一点是,假设我们有2个数字,其素数因子分解包含公共素数,那么这两个元素不能在不同的子阵列中,因为GCD不会是1(根据要求题)。因此,对于所有这样的对,它们必须处于相同的子阵列中。怎么做到这一点?
我们可以创建一个不相交的所有素数集。因此,开头的集合数量将是素数的数量。然后,在每个分解期间,我们将加入作为除数的所有素数,并将它们全部添加到具有原始数字的同一组中。这将对所有数字重复。
此外,我们必须检查一次,是否首先需要一些素数。因为在此步骤之前我们假设存在与范围中的素数一样多的集合。但有些可能未被使用。因此,可以通过遍历一次循环并查找唯一代表的数量来检查。这将是我们的答案。
我的代码:
#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;
}