传送门
题目大意
给你 n n n个数,去掉尽量少的数使得剩下数的 g c d gcd gcd比原来的大,无解输出 − 1 -1 −1。
思路
先求出所有数的 g c d gcd gcd,然后每个数都除以 g c d gcd gcd,想要 g c d gcd gcd变大,就应该在剩下的数的质因子找到质因子出现次数最多的 c n t cnt cnt,然后答案就是 n − c n t n-cnt n−cnt。
代码
int n;
ll a[maxn];
bool vis[maxn];//标记非素数,0是素数
int primer[maxn/10];//存素数
int cnt=0;//记录素数个数,
void find_primer(){
for(int i=2;i<=maxn;i++){
if(!vis[i])primer[cnt++]=i;
for(int j=0;j<cnt&&primer[j]*i<=maxn;j++){
vis[i*primer[j]]=1;//筛
if(i%primer[j]==0)break;//关键!!!找到i*primer[j]的最小质因子primer[j],退出
}
}
}
map<int,int>mp;
void init(int x){
for(int i=0;i<cnt&&primer[i]*primer[i]<=x;i++){
if(x%primer[i]==0){
while(x%primer[i]==0){
x/=primer[i];
}
mp[primer[i]]++;
}
}
if(x>1) mp[x]++;
}
int x[maxn];
int gcd(int a,int b) {
return b == 0 ? a : gcd(b, a%b);
}
int main(){
find_primer();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x[i]);
}int xx=x[1];
for(int i=2;i<=n;i++){
xx=gcd(xx,x[i]);
}
for(int i=1;i<=n;i++){
x[i]=x[i]/xx;
init(x[i]);
}
map<int,int>::iterator it;
int ans=-1;
for(it=mp.begin();it!=mp.end();it++){
int tmp=it->second;
//cout<<it->first<<" "<<it->second<<endl;
ans=max(ans,it->second);
}
if(ans==0||ans==-1){
puts("-1");
return 0;
}
printf("%d",n-ans);
}