题意:
给定n个数,删掉最少的数使剩余所有数的最大公约数比删除前所有数的最大公约数大
思路:
先算出所有数的最大公约数g,并将所有数 / g,这时序列内全部数的最大公约数为1,这时我们只要找到序列中每个质数的倍数最多有多少个(设有m个)。
如果全部数为1,输出-1。否则,输出n - m。
注意:直接枚举每个数的质因子会超时,在线筛中记录每个数的最小质因子,优化质因子分解即可。
Code:
#pragma GCC optimize(3) #pragma GCC optimize(2) #include <map> #include <set> #include <array> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <cstring> #include <sstream> #include <iostream> #include <stdlib.h> #include <algorithm> #include <unordered_map> using namespace std; typedef long long ll; typedef pair<int, int> PII; #define Time (double)clock() / CLOCKS_PER_SEC #define sd(a) scanf("%d", &a) #define sdd(a, b) scanf("%d%d", &a, &b) #define slld(a) scanf("%lld", &a) #define slldd(a, b) scanf("%lld%lld", &a, &b) const int N = 1e6 + 20; const int M = 1.5e7 + 20; const int mod = 1e9 + 7; int n; map<int, int> mp; int a[N]; int primes[M], cnt = 0, mind[M]; bool st[M]; void get(int n) { for (int i = 2; i <= n; i++) { if (!st[i]){ primes[cnt++] = i; mind[i] = i; } for (int j = 0; primes[j] <= n / i; j++) { st[i * primes[j]] = true; mind[i * primes[j]] = primes[j]; if (i % primes[j] == 0) { break; } } } } void solve() { sd(n); sd(a[0]); int mid = a[0]; for (int i = 1; i < n; i++) { sd(a[i]); mid = __gcd(mid, a[i]); } get(M - 20); for (int i = 0; i < n; i++) { a[i] /= mid; while(a[i] > 1){ int d = mind[a[i]]; mp[d] ++; while(a[i] % d == 0){ a[i] /= d; } } } int m = 0; for (auto x : mp) { m = max(m, x.second); } if (m == 0) cout << "-1 "; else cout << n - m << " "; } int main() { #ifdef ONLINE_JUDGE #else freopen("/home/jungu/code/in.txt", "r", stdin); // freopen("/home/jungu/code/out.txt", "w", stdout); // freopen("/home/jungu/code/out.txt","w",stdout); #endif // ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int T = 1; // sd(T); while(T --){ solve(); } return 0; }