A - Enlarge GCD
题意:给n个数,那么他们有gcd,去掉最多n-1个数使得他们的gcd变大。求去掉最少的数。
题解:首先如果所有数都相等,那么无解。否则一定有解:最多去掉只剩下最大的那个。gcd是没有影响的,可以直接除掉(注意gcd可以用0来初始化,0和x的gcd都等于x)。然后除去gcd之后每个数有他独特的几种因子,把不含这种因子的数都去掉就可以把这种因子释放出来。暴力sqrt分解会T掉,线性筛/埃筛预处理出每个数的最小质因子(甚至不需要预处理出他的幂,反正除一除也是log级别的)就把复杂度降低到质因子的最大个数(当一直除时,大概27左右)或者质因子的种类(当预处理出每个数含有的最小质因子的幂时,不超过8个),比sqrt的大概4000要快100倍。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 1e7 + 5e6; int p[970704 + 5], ptop; int pm[MAXN + 5], pk[MAXN + 5]; void sieve() { int n = MAXN; pm[1] = 1; pk[1] = 1; for(int i = 2; i <= n; i++) { if(!pm[i]) { p[++ptop] = i; pm[i] = i; pk[i] = i; } for(int j = 1; j <= ptop; j++) { int t = i * p[j]; if(t > n) break; pm[t] = p[j]; if(i % p[j]) { pk[t] = pk[p[j]]; } else { pk[t] = pk[i] * p[j]; break; } } //printf("i=%d pm=%d pk=%d\n", i, pm[i], pk[i]); } //printf("ptop=%d\n",ptop); /*for(int i=1;i<=ptop;++i) printf("%d:%d\n",i,p[i]);*/ } int a[300005]; int ans[MAXN + 5]; void test_case() { int n, cnt1 = 0; scanf("%d", &n); int gcd = 0; for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]); gcd = __gcd(gcd, a[i]); } for(int i = 1; i <= n; ++i) { a[i] /= gcd; while(a[i] > 1) { ans[pm[a[i]]]++; a[i] /= pk[a[i]]; } } int minans = n; for(int i = 1; i <= MAXN; ++i) minans = min(minans, n - ans[i]); printf("%d\n", minans == n ? -1 : minans); }