删去最少的数,使gcd变大
这个题目写了我好久,学到了新知识,质因数分解可以logn分解,以前一直以为是 n \sqrt{n} n ,可以直接用素数筛,筛出所有合数的最小质因子,然后就直接logn分解了,其他的不是很难,就是简单的分解就行了
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define debug printf("I am here\n");
using namespace std;
typedef long long ll;
const int maxn=3e5+5,inf=0x3f3f3f3f,mod=998244353,lim=1e7+5e6;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,a[maxn],tot[lim+5],g;
int prime[lim+5],isprime[lim+5],cnt;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void getprime(){
for(ll i=2;i<=lim;i++){
if(isprime[i]==0){
prime[++cnt]=i;
}
for(ll j=1;j<=cnt&&i*prime[j]<=lim;j++){
isprime[i*prime[j]]=prime[j];
if(i%prime[j]==0){
break;
}
}
}// cnt:970704
}
int main(){
getprime();
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(i==1){
g=a[i];
}else{
g=gcd(g,a[i]);
}
}
for(int i=1;i<=n;i++){
a[i]=a[i]/g;
while(isprime[a[i]]){
int p=isprime[a[i]];
while(a[i]%p==0){
a[i]=a[i]/p;
}
tot[p]++;
}
if(a[i]!=1){
tot[a[i]]++;
}
}
int ans=n;
for(int i=1;i<=cnt;i++){
ans=min(ans,n-tot[prime[i]]);
}
if(ans==n){
ans=-1;
}
printf("%d\n",ans);
return 0;
}