传送门
文章目录
- 目录
- 题意:
- 思路:
目录
题意:
给你一个长度为nnn的数组,你每次可以选择其中的两个数,如果他们的gcdgcdgcd在数组中没有出现那么就可以加在数组后面构成一个新的数组,问数组最长是多少。
2≤n≤1e6,1≤ai≤1e62\le n\le 1e6,1\le a_i\le 1e62≤n≤1e6,1≤ai≤1e6
思路:
设cnt[i]cnt[i]cnt[i]表示包含因子iii的数有多少个,但是想要判断两个数的gcd==igcd==igcd==i只靠cnt[i]>1cnt[i]>1cnt[i]>1是不够的,因为不能保证其中两个数的最大公因数是iii,但是我我们如果枚举包含以iii为因子的数jjj,如果存在cnt[i]==cnt[j]cnt[i]==cnt[j]cnt[i]==cnt[j],那么一定不存在两个数的最大公因数是iii,因为这个时候这些数最大公因数是jjj。当不存在上述情况且有两个x,yx,yx,y满足cnt[x]>0,cnt[y]>0cnt[x]>0,cnt[y]>0cnt[x]>0,cnt[y]>0,那么此时这两个集合中的数最大公因数一定是iii,直接nlognnlognnlogn求即可。
#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;
}