CF1034A 题解

CF1034A

思路

先对 \(a_i\)\(\operatorname{gcd}\)\(g\) 表示数组的 \(\operatorname{gcd}\)

每个 \(a_i\) 除以 \(g\)。要找出一个质数,使得有最多的除以 \(g\) 后的 \(a_i\) 整除该质数。对 \(a_i\) 做质因数分解,舍去重复的质数因子,加入桶中。最后枚举答案 \(ans=\min {n-t_i}\)\(n-t_i\) 即要删除的数的个数。

\(\max a_i\) 内的质数做素数筛,复杂度 \(O(a_i)\)。在素数筛向后转移的同时,标记 \(vis_{i\times pre_j}\)\(1\) 时,记录 \(f_{i\times pre_j}=pre_j\),即 \(i\times pre_j\) 有一个质因数 \(pre_j\)。对 \(x\) 做质因数分解时,\(x\) 不断除以 \(f_x\) 直到 \(x=1\)。在分解过程中,所有的 \(f_x\)\(x\) 的质因数。因为 \(a_i\) 最多有 \(\log a_i\) 质因子,所以总复杂度 \(O(n\log a_i+a_i)\),可以接受。

code

int n,a[maxn],g,ans=inf,mx;
bool vis[maxm];
int pre[maxn],cnt;
int f[maxm],t[maxm];
void s(int n){
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			pre[++cnt]=i;
			f[i]=i;
		}
		for(int j=1;j<=cnt&&i*pre[j]<=n;j++){
			f[i*pre[j]]=pre[j];
			vis[i*pre[j]]=1;
			if(i%pre[j]==0)break;
		}
	}
}

signed main(){
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		if(i==1)g=a[1];
		else g=__gcd(g,a[i]);
	}
	for(int i=1;i<=n;i++){
		a[i]/=g;
		mx=max(mx,a[i]);
	}
	s(mx);
	for(int i=1;i<=n;i++){
		int lst=0;
		while(a[i]!=1){
			if(lst!=f[a[i]]){
				lst=f[a[i]];
				t[lst]++;
			}
			a[i]/=f[a[i]];
		}
	}
	for(int i=1;i<=mx;i++)ans=min(ans,n-t[i]);
	if(ans==n)printf("-1\n");
	else printf("%d\n",ans); 
}
posted @ 2024-05-10 19:51  yhddd  阅读(14)  评论(0)    收藏  举报