http://codeforces.com/contest/1047/problem/C
问题
给一个序列 \(A\),计原序列所有数的最大公约数为 \(p\)。现在要删除一些数形成一个新序列,计新序列所有数的最大公约数为 \(q\) 问最少删除多少数能使 \(q > p\)。
题解
先求出 \(p\),然后枚举 \(q > p\),计算一下序列中 \(q\) 的倍数有哪些。注意到若存在 \(a | q\) 且 \(a > p\),那么 \(a\) 显然优于 \(p\),因此用一个类似筛法的方法枚举就好了,复杂度 \(O(N \cdot \log{\log{N}})\) 。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
int rint() {
int n, c, sgn = 0;
while ((c = getchar()) < ‘-‘);
if (c == ‘-‘) n = 0, sgn = 1;
else n = c - ‘0‘;
while ((c = getchar()) >= ‘0‘) {
n = 10 * n + c - ‘0‘;
}
return sgn ? -n : n;
}
const int N = 300010;
const int MAX = 1.5e7 + 10;
int n;
bool mark[MAX];
int cnt[MAX];
int main() {
scanf("%d", &n);
int g = 0;
for (int i = 0; i < n; i++) {
int x;
scanf("%d", &x);
cnt[x]++;
g = __gcd(g, x);
}
int ans = n;
for (int d = g + 1; d < MAX; d++) {
if (mark[d]) continue;
int need = 0;
for (ll j = d; j < MAX; j += d) {
mark[j] = true;
need += cnt[j];
}
if (need > 0) {
ans = min(ans, n - need);
}
}
if (ans == n) puts("-1");
else printf("%d\n", ans);
fprintf(stderr, "%.3lf sec\n", double(clock()) / CLOCKS_PER_SEC);
return 0;
}
原文地址:https://www.cnblogs.com/hfccccccccccccc/p/9777475.html
时间: 2024-10-13 14:26:22