C. Enlarge GCD
https://codeforces.com/contest/1047/problem/C
题目大意:给一个数组,问最少删除多少个数可使得剩下的数的最大公约数比原来的大。
思路:1<=a <= 1.5*10^7,不算大,可以考虑筛法。题目中要求剩下数的最大公约数比原来的最大公约数大,设原数组的最大公约数为g,所以可以用>g的数去枚举原数组中有多少的数可以整除这个数,这些数的最大公约数就是这个数了(不会证…),那么此时要删除的数也就可以求出来了,最后取一个最小值就是答案。。用来筛公约数的那个数不能是之前数的倍数,(参考埃式筛),不然会超时. (只剩一个数的时候最大公约数是它自身)。
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define pf printf
#define pq priority_queue
#define sc(x) scanf("%d", &x)
#define scl(x) scanf("%lld", &x)
#define rep(i, s, e) for(int i = s;i <= e; ++ i)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
const int M = 15000010;
const int N = 300000;
int t;
int n, m, a[N], maxn;
int vis[M];
bool p[M];
int main()
{
scanf("%d", &n);
int g = 0;
for(int i = 1;i <= n; ++ i) {
scanf("%d", &a[i]);
maxn = max(a[i], maxn);
vis[a[i]] ++;
}
g = a[1];
for(int i = 2;i <= n; ++ i) g = __gcd(a[i], g);
int res = 9999999;
for(int i = g + 1;i <= maxn; ++ i) {
if(p[i]) continue;
int cnt = 0;
for(int j = i;j <= maxn; j += i){
if(vis[j]) cnt += vis[j];
p[j] = true;
}
if(cnt > 0)
res = min(res, n-cnt);
}
if(res == 9999999) puts("-1");
else printf("%d\n", res);
}