Codeforces 1034A Enlarge GCD(素数筛选)
题目大意
删去最少的数使剩下的数的\(gcd\)比原来大。
分析
既然要比来的的\(gcd\)大,那么一定是在原来\(gcd\)基础上乘上某一个数。而又要删除的数最少,那么考虑乘的这个数为素数时可得最优解,这个素数应该是尽量多的数字的质因子。
具体实现
将所有数字的\(gcd\)求出来然后除去它,再找一个素数,它是尽量多的数字的质因子就行了。可以先写一个欧拉筛得到每个数的最小质因子,然后质因数分解,让这个数不断的除以自己的最小质因子,再让剩下的数除以自己的最小质因子就行了,这个分解方法比试除法快一些,不过比较占内存,但是题目给的内存还是绰绰有余的。最后统计出出现次数最多的质因子就是我们保留的数字,在它们之外就是应该删除的数字。
const int maxn = 3e5+10;
const int maxn2 = 1.5e7+10;
int arr[maxn], u[maxn2], p[maxn2], cnt[maxn2], n, kase;
void pri() {
for (int i = 2; i<maxn2; ++i) {
if (!u[i]) u[i] = p[++kase] = i;
for (int j = 1; i*p[j]<maxn2; ++j) {
u[i*p[j]] = p[j];
if (!(i%p[j])) break;
}
}
}
int main(void) {
pri();
scanf("%d", &n);
int g = 0;
for (int i = 0; i<n; ++i) {
scanf("%d", &arr[i]);
g = __gcd(g, arr[i]);
}
int maxx = -1;
for (int i = 0, x; i<n; ++i) {
arr[i] /= g;
while(arr[i]>1) {
x = u[arr[i]];
while(x == u[arr[i]]) arr[i] /= x;
maxx = max(maxx, ++cnt[x]);
}
}
printf("%d\n", ~maxx ? n-maxx : maxx);
return 0;
}