CF1034A Enlarge GCD
Posted forwardfuture
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1034A Enlarge GCD相关的知识,希望对你有一定的参考价值。
题意:给你(n)个数,去掉尽量少的数使得剩下数的(gcd)比原来的大,无解输出(-1)
题目意思很简洁,想理出来一个清晰的思路却花了不少时间......首先先计算出总的(GCD),然后再把每个数都除去这个(GCD),接下来的事情就得仔细考虑一下了。
设(M=maxleft{a[i] ight}),则若枚举(1-M)内所有质数(显然枚举质数比合数优)并一一判断在(1-n)中整除它们的数字的个数,复杂度为(O(frac{nM}{log,M}))必须爆炸。当时想到这里就优化不下去了,于是凉凉。实际上有一种看似暴力的方法可以较优地解决这个问题:我们开一个数组(b[i]),并在每一个(b[a[i]])的位置上加一,那么当我们枚举质数的时候将其所有倍数上的数组(b)的值加在一起就可以更新答案了。运行次数大概是(sum limits_{i为质数且i le M}frac{M}{i}),这东西收敛得比较快,所以复杂度可以接受。
代码如下:
#include<cstdio>
#include<iostream>
#define INF 1000000000
using namespace std;
const int N=3e5+10;
const int M=1.5e7+10;
int n,a[N],GCD,primes[M],v[M],cnt,num[M],sum,ans=INF,maxn;
inline int exgcd(int x,int y){int r;while(x&&y){r=x%y;x=y;y=r;}return x;}
inline void Primes_Table(){
for(register int i=2;i<=M-10;i++){
if(!v[i]){v[i]=i;primes[++cnt]=i;}
for(register int j=1;j<=cnt&&i*primes[j]<=M-10;j++){
if(v[i]<primes[j])continue;v[i*primes[j]]=primes[j];}
}
}
int main(){
Primes_Table();scanf("%d",&n);
for(register int i=1;i<=n;i++)scanf("%d",&a[i]);
GCD=a[1];for(register int i=2;i<=n;i++)GCD=exgcd(GCD,a[i]);
for(register int i=1;i<=n;i++)a[i]/=GCD,maxn=max(maxn,a[i]);
for(register int i=1;i<=n;i++)num[a[i]]++;
for(register int i=1;i<=cnt;i++){sum=0;
for(register int j=primes[i];j<=maxn;j+=primes[i])sum+=num[j];
ans=min(ans,n-sum);}
printf("%d
",ans==n? -1:ans);return 0;
}
以上是关于CF1034A Enlarge GCD的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 1047C Enlarge GCD(数论)题解
C. Enlarge GCD Codeforces Round #511 (Div. 2)数学
Codeforces Round #511 (Div. 2)-C - Enlarge GCD (素数筛)