首页 > 代码库 > 51nod 1616 最小集合(枚举倍数)
51nod 1616 最小集合(枚举倍数)
分析:也就是取任意多个数,它们的最大公约数都在这个集合里。考虑到ai比较小,可以枚举小于a中最大值的所有数,判断是否为其中若干个数的gcd。记c[k]为a中k的倍数的个数,然后枚举k的倍数i*k,c[i]<2直接跳过,如果c[i*k]==c[k],说明k的那些倍数也同时是i*k的倍数,k就可以不在集合中,反之,如果任意i,c[i*k]<c[k],说明存在一个倍数和其它k的倍数的gcd是k,所以k一定在集合中。两次枚举倍数,复杂度为O(nlogn)。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int maxn=1e6+5; 6 bool In_set[maxn]; 7 int count_multiple[maxn]; 8 int main(){ 9 int n,ans=0,a; 10 scanf("%d",&n); 11 ans=n; 12 memset(In_set,0,sizeof(In_set)); 13 memset(count_multiple,0,sizeof(count_multiple)); 14 for(int i=0;i<n;i++){ 15 scanf("%d",&a); 16 if(In_set[a])ans--; 17 In_set[a]=true; 18 } 19 for(int i=1;i<maxn;i++){ 20 //if(In_set[i])continue; 21 for(int j=i;j<maxn;j+=i){ 22 if(In_set[j]) 23 count_multiple[i]++; 24 } 25 } 26 for(int i=1;i<maxn;i++){ 27 if(In_set[i]||count_multiple[i]<2)continue; 28 bool ok=true; 29 for(int j=2*i;j<maxn;j+=i){ 30 if(count_multiple[j]==count_multiple[i]){ 31 ok=false;break; 32 } 33 } 34 if(ok) 35 ans++; 36 } 37 cout<<ans<<endl; 38 return 0; 39 }
51nod 1616 最小集合(枚举倍数)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。