Codeforces Round #511 Div2 C. Enlarge GCD

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

Codeforces Round #511 Div2 C. Enlarge GCD的相关文章

Codeforces Round #511 Div2 D. Little C Loves 3 II

http://codeforces.com/contest/1047/problem/D 问题 有一个 \(N \times M\) 的棋盘,每次可以选择两个曼哈顿距离为 \(3\) 的未被占领的点,并在这两个点上放置棋子.问最多能放多少个旗子. 题解 建图跑了一下最大流会发现基本都可以跑满,只有部分小数据跑不满,特判一下就好了... #include <bits/stdc++.h> #ifdef LOCAL #define debug(...) fprintf(stderr, __VA_AR

codeforces round #257 div2 C、D

本来应该认真做这场的,思路都是正确的. C题,是先该横切完或竖切完,无法满足刀数要求,再考虑横切+竖切(竖切+横切), 因为横切+竖切(或竖切+横切)会对切割的东西产生交叉份数,从而最小的部分不会尽可能的大. 代码如下,虽然比较长.比较乱,但完全可以压缩到几行,因为几乎是4小块重复的代码,自己也懒得压缩 注意一点,比如要判断最小块的时候,比如9行要分成2份,最小的剩下那份不是9取模2,而应该是4 m/(k+1)<=m-m/(k+1)*k          #include<bits/stdc+

codeforces Round #250 (div2)

a题,就不说了吧 b题,直接从大到小排序1-limit的所有数的lowbit,再从大到小贪心组成sum就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200000 6 using namespace std; 7 int pos[N],a[N],s[N],f[N],la[N],b[N],i,j,k,ans,n,p

Codeforces Round#320 Div2 解题报告

Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Finding Team Member codeforces 579C A Problem about Polyline codeforces 579D "Or" Game codeforces 579E Weakness and Poorness codeforces 579F LCS Aga

Codeforces Round #254(div2)A

很有趣的题.想到了就非常简单,想不到就麻烦了. 其实就是一种逆向思维:最后结果肯定是这样子: WBWBWBWB... BWBWBWBW... WBWBWBWB... ... 里面有“-”的地方改成“-”就行了. 但是我开始是正着想的,想每个点怎么处理,这还要看它周围点的状态,越想越麻烦... 这题中体现的正难则反的逆向思维很值得学习. #include<iostream> #include<cstdio> #include<cstdlib> #include<cs

Codeforces Round #254(div2)B

就是看无向图有几个连通块,答案就是2n-num. 范围很小,就用矩阵来存图减少代码量. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #inc

Codeforces Round #260(div2)C(递推)

有明显的递推关系: f[i]表示i为数列中最大值时所求结果.num[i]表示数i在数列中出现了几次. 对于数i,要么删i,要么删i-1,只有这两种情况,且子问题还是一样的思路.那么很显然递推一下就行了:f[i]=max(f[i-1],f[i-2]+i*num[i]); 这里技巧在于:为了防止麻烦,干脆就所有数的出现次数都记录一下,然后直接从2推到100000(类似于下标排序),就不用排序了,也不用模拟删除操作了.这一技巧貌似简单,但实际上临场想出来也需要点水平. #include<iostrea

Codeforces Round #289 Div2 E

Problem 给一串长度为N的字符串,对于每个字符,若字符为元音,则权值为1,否则为0.一个子串的权值定义为该串所有字符权值之和除以字符个数,一个母串的权值定义为所有子串的权值之和.求母串的权值. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N: [1, 5*10^5] 字符集: 'A'-'Z' 元音: I E A O U Y Solution 考虑每个元音字符对母串的贡献,可以找出规律. More 举"ABCDOEFGHKMN"

Codeforces Round #403 div2 C. Andryusha and Colored Balloons

题目链接:Codeforces Round #403 div2 C. Andryusha and Colored Balloons 题意: 给你一棵n个节点的树,然后让你染色,规定相连的三个 节点不能同色,问需要的最少颜色,并输出其中一种方案. 题解: 因为只有相邻3个节点不同色. 所以直接DFS,每个节点都从1开始. 然后ans[v]!=ans[u]!=ans[fa]就行. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i&