[题目链接]
https://codeforces.com/contest/1047/problem/C
[算法]
首先求出n个数的最大公约数g , 将每个数除以g , 那么 , 问题就转化为在n个数中选出一个数集 , 使得这个数集中的数最大公约数不为1 , 最大化数集大小
预处理Ai范围内的质数 , 然后对于每个数分解质因数即可
时间复杂度 : O(NlogN + N log V)
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 3e5 + 10; const int MAXP = 1.5e7 + 10; int n,tot; int a[MAXN],prime[MAXP],f[MAXP],cnt[MAXP]; template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline int gcd(int x,int y) { if (y == 0) return x; else return gcd(y,x % y); } int main() { read(n); for (int i = 1; i <= n; i++) read(a[i]); int g = a[1]; for (int i = 2; i <= n; i++) g = gcd(g,a[i]); for (int i = 1; i <= n; i++) a[i] /= g; for (int i = 2; i < MAXP; i++) { if (!f[i]) { f[i] = i; prime[++tot] = i; } for (int j = 1; j <= tot; j++) { int tmp = i * prime[j]; if (tmp > MAXP) break; f[tmp] = prime[j]; if (prime[j] == f[i]) break; } } int ans = -1; for (int i = 1; i <= n; i++) { int pre = -1 , tmp = a[i]; while (tmp != 1) { if (f[tmp] == pre) { tmp /= f[tmp]; continue; } cnt[f[tmp]]++; if (cnt[f[tmp]] > ans) ans = cnt[f[tmp]]; pre = f[tmp]; tmp /= f[tmp]; } } if (ans == -1) printf("-1 "); else printf("%d ",n - ans); return 0; }