给定< code>n,数组元素的数目和< code>arr[n],数字数组,需要找到数组可以分成的子数组的最大数目,使得对于属于不同子数组的每个< code>a和< code>b,< code>GCD(a,b)=1。
例如:
5
2 3 4 5 6
Ans: 2 ----> {(2,3,4,6),(5)}
任何其他进一步分裂它的企图都不会满足这些条件。
我的方法:
1.对数组进行排序
2.继续计算元素的lcm
3.每当元素的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;
}
在我的答案被多次判断为
错误答案
之后,我很困惑我的答案是否正确。由于n
的限制为10^6
,数组元素为10^7
,因此解决方案失败的另一个原因是
我认为这就是您所指的问题:https://www.codechef.com/problems/CHEFGRUP
我的方法如下(我超过了时间限制):
这可以使用埃拉托色尼筛来完成,复杂度将是O(nlog(log(n))
其中n最多可以是10^7
。
一旦我们有了所有需要的质数,这就可以非常有效地实现。
在这一步中需要注意的一点是,假设我们有两个数,其素数分解包含公共素数,那么这两个元素不能在不同的子数组中,因为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;
}
有没有一种方法可以在小于O(n^2)的时间内做到这一点。 O(nlogn)还是O(n)?
我有一个由32个数字组成的数组[1,2,3,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,7,7,7,7,8,9,10,10,11,9,12,13,13,14,14,15,16,17,17] 对于我最初的问题,我不需要生成所有的排列。我只需要在每次运行我的程序时生成一个随机排列。 我的方法是使用Fisher-Yates算法随机洗牌数组,并不断重新洗牌,直到我得到所有8个子数组,没有重
O(n^2)算法简单。有没有人对此有更好的算法?
问题内容: 我有很多对象,我需要将它们分成两个组成一组,以供UI助手使用。 例: 通过这四个数组成为一个数组 有很多分割数组的方法。但是,如果阵列很大,什么是最有效的(成本最低)。 问题答案: 如果您正在寻找效率,则可以使用一种方法来懒散地生成每个包含2个元素的数组,因此您一次只能在内存中存储2个元素: 此方法适用于任何Array,而不仅限于Arrays。 对于Swift 1,没有协议扩展,您将拥
给定一个数字数组,查找是否有方法从数组中删除/移除一个数字,并在数组中进行一个分区(将数组划分为两个子数组),以使子数组1中的元素和等于子数组2中的元素和。 现在让我们考虑一个例子:- 现在一个类似的问题已经存在,我们只需要,找到是否数组可以被分成两个子数组相等的和,可以在O(n) =中完成 伪代码:-有效的解决方案包括提前计算阵列中所有元素的总和。然后,对于数组中的每个元素,我们可以通过使用数组