Codeforces Round #511 Enlarge GCD

链接

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 Nk个数字才能使得最终的 g c d gcd gcd不包含这个素数因子
把所有数字按照值装进一个桶里,然后枚举素数统计下 N − k N-k Nk的最小值就是答案了,别忘了加上一开始删掉的 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;
}

你可能感兴趣的:(#,数学杂题)