链接
http://codeforces.com/contest/1047/problem/C
题解
先筛出所有的素数
输入的
n
n
n个数字首先要删掉所有的
1
1
1,因为如果不删掉
1
1
1,
g
c
d
gcd
gcd就永远是
1
1
1
所有数字相等的情况无解,否则一定有解
剩下的数字,如果
g
c
d
gcd
gcd还是
1
1
1,那么就枚举每个素数,看看这个素数在哪些数字中出现了,假设这个数字在
k
k
k个数中出现了,那么我只需要删掉
N
−
k
N-k
N−k个数字才能使得最终的
g
c
d
gcd
gcd不包含这个素数因子
把所有数字按照值装进一个桶里,然后枚举素数统计下
N
−
k
N-k
N−k的最小值就是答案了,别忘了加上一开始删掉的
1
1
1的个数
代码
#include <bits/stdc++.h>
#define ll long long
#define cl(x) memset(x,0,sizeof(x))
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define dinf 1e100
#define eps 1e-8
#define maxn 300010
#define maxa 15000010
using namespace std;
int read(ll x=0)
{
int f=1, c;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
int N, prime[maxa], cnt[maxa], a[maxn], g, c1;
bool mark[maxa];
void shai()
{
int i, j;
for(i=2;i<maxa;i++)
{
if(!mark[i])prime[++*prime]=i;
for(j=1;j<=*prime and i*prime[j]<maxa;j++)
{
mark[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
int gcd(int a, int b){return !b?a:gcd(b,a%b);}
void init()
{
int i, x=0;
N=read();
for(i=1;i<=N;i++)
{
a[i]=read();
if(a[i]==1)c1++;
else a[++x]=a[i];
}
N=x;
}
void work()
{
int i, j, g, ans=iinf, c;
if(!N) //全是1无解
{
printf("-1");
return;
}
if(c1==0) //没有1,都相等也无解
{
for(i=2;i<=N;i++)if(a[i]!=a[i-1])break;
if(i>N)
{
printf("-1");
return;
}
}
for(g=a[1],i=2;i<=N;i++)g=gcd(g,a[i]);
if(c1>0 and g!=1) //删完1就结束了
{
printf("%d",c1);
return;
}
for(i=1;i<=N;i++)cnt[a[i]]++;
for(i=1;i<=*prime;i++)
{
c=0;
for(j=prime[i];j<maxa;j+=prime[i])c+=cnt[j];
ans=min(ans,c1+N-c);
}
printf("%d",ans);
}
int main()
{
shai();
init();
work();
return 0;
}