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
#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;
}