目录
题意:
给你一个长度为 n n n的数组,你每次可以选择其中的两个数,如果他们的 g c d gcd gcd在数组中没有出现那么就可以加在数组后面构成一个新的数组,问数组最长是多少。
2 ≤ n ≤ 1 e 6 , 1 ≤ a i ≤ 1 e 6 2\le n\le 1e6,1\le a_i\le 1e6 2≤n≤1e6,1≤ai≤1e6
思路:
设 c n t [ i ] cnt[i] cnt[i]表示包含因子 i i i的数有多少个,但是想要判断两个数的 g c d = = i gcd==i gcd==i只靠 c n t [ i ] > 1 cnt[i]>1 cnt[i]>1是不够的,因为不能保证其中两个数的最大公因数是 i i i,但是我我们如果枚举包含以 i i i为因子的数 j j j,如果存在 c n t [ i ] = = c n t [ j ] cnt[i]==cnt[j] cnt[i]==cnt[j],那么一定不存在两个数的最大公因数是 i i i,因为这个时候这些数最大公因数是 j j j。当不存在上述情况且有两个 x , y x,y x,y满足 c n t [ x ] > 0 , c n t [ y ] > 0 cnt[x]>0,cnt[y]>0 cnt[x]>0,cnt[y]>0,那么此时这两个集合中的数最大公因数一定是 i i i,直接 n l o g n nlogn nlogn求即可。
#include<bits/stdc++.h>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define Mid (tr[u].l+tr[u].r>>1)
#define pb push_back
using namespace std;
const int N=1000260,INF=0x3f3f3f3f,mod=1e9+7;
typedef long long LL;
typedef pair<int,int> PII;
int n;
int a[N],mp[N],cnt[N];
int gc[N];
void solve() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
mp[a[i]]=1; cnt[a[i]]=1;
}
int ans=0;
for(int i=1;i<=1e6;i++) {
for(int j=i+i;j<=1e6;j+=i) {
cnt[i]+=cnt[j];
}
}
for(int i=1;i<=1e6;i++) {
int flag=cnt[i]>0;
for(int j=i+i;j<=1e6;j+=i) {
if(cnt[i]==cnt[j]) flag=0;
}
ans+=flag;
}
printf("%d\n",ans-n);
}
int main() {
int _=1;
while(_--) {
solve();
}
return 0;
}