题意:n个数的gcd是k,要你删掉最少的数使得删完后的数组的gcd > k
思路:先求出k,然后每个数除以k。然后找出出现次数最多的质因数即可。
代码:
#include<cmath> #include<set> #include<map> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> #include<unordered_map> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 3e5 + 10; const int M = 1.5 * 1e7 + 10; const ull seed = 131; const int INF = 0x3f3f3f3f; const int MOD = 1e4 + 7; int gcd(int a, int b){ return b == 0? a : gcd(b, a % b); } int a[maxn]; int p[4000], prime[4000], pn; int num[M]; void init(){ pn = 0; memset(p, 0, sizeof(p)); for(int i = 2; i < 4000; i++){ if(!p[i]){ prime[pn++] = i; } for(ll j = 0; j < pn && i * prime[j] < 4000; j++){ p[i * prime[j]] = 1; if(i % prime[j] == 0) continue; } } // printf("%d\n", pn); } int main(){ int n, need; init(); scanf("%d", &n); memset(num, 0, sizeof(num)); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); if(i == 1) need = a[i]; else need = gcd(need, a[i]); } for(int i = 1 ; i <= n; i++) a[i] /= need; int ans = -1; for(int i = 1; i <= n; i++){ for(int j = 0; j < pn && prime[j] * prime[j] <= a[i]; j++){ if(a[i] % prime[j] == 0){ num[prime[j]]++; ans = max(ans, num[prime[j]]); while(a[i] % prime[j] == 0) a[i] /= prime[j]; } } if(a[i] > 1){ num[a[i]]++; ans = max(ans, num[a[i]]); } } if(ans == -1) printf("%d\n", ans); else printf("%d\n", n - ans); return 0; }