zoukankan      html  css  js  c++  java
  • 【题解】[Ghd]

    【题解】Ghd

    一道概率非酋题?

    题目很有意思,要我们选出大于(frac{n}{2})个数字使得他们的最大公约数最大。

    那么我们若随便选择一个数字,他在答案的集合里的概率就大于(0.5)了。

    我们若连续随机选择(10)次,那么我们答案判断失误的概率不就是(frac{1}{2^{10}}< frac{1}{1000})吗?

    除非你脸黑不然不可能错吧233

    那么我们这样,每次随机选择出来的数字,先对所有数取(gcd)然后再将出现次数放入(map)一一检查答案即可。

    时间复杂度(O(nlogn))有一些其他的常数,不算了。

    蒯的代码,咕咕咕

    #include <cstdio>
    #include <ctime>
    #include <cstdlib>
    
    #include <map>
    
    typedef long long LL;
    
    inline char fgc() {
        static char buf[100000], *p1 = buf, *p2 = buf;
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
    }
    
    inline LL readint() {
        register LL res = 0, neg = 1;
        char c = fgc();
        while(c < '0' || c > '9') {
            if(c == '-') neg = -1;
            c = fgc();
        }
        while(c >= '0' && c <= '9') {
            res = res * 10 + c - '0';
            c = fgc();
        }
        return res * neg;
    }
    
    const int MAXN = 1000005;
    
    inline LL gcd(LL a, LL b) {
        LL t;
        while(b) {
            t = a % b;
            a = b;
            b = t;
        }
        return a;
    }
    
    int n;
    LL a[MAXN];
    
    int main() {
        srand(time(NULL));
        n = readint();
        for(int i = 1; i <= n; i++) {
            a[i] = readint();
        }
        LL ans = 1;
        for(int rep = 1; rep <= 10; rep++) {
            int rnd = (rand() * RAND_MAX + rand()) % n + 1;
            // 下面我们需要处理出a[rnd]和其他数的gcd,答案可能就是这些gcd中的一个,map里first存gcd,second存该gcd的出现次数
            std::map<LL, int> fact;
            for(int i = 1; i <= n; i++) {
                LL t = gcd(a[i], a[rnd]);
                if(!fact.count(t)) fact[t] = 1;
                else fact[t]++;
            }
            // 从大到小来判断每个gcd是否能成为答案
            std::map<LL, int>::iterator it = fact.end();
            do {
                it--;
                if((*it).first <= ans) continue;
                int cnt = 0;
                // 能被当前答案整除的因数对应的原数肯定能够被当前答案整除,统计能被当前答案整除的数字个数
                for(std::map<LL, int>::iterator it1 = it; it1 != fact.end() && cnt << 1 < n; it1++) {
                    if(!((*it1).first % (*it).first)) {
                        cnt += (*it1).second;
                    }
                }
                // 如果能被当前答案整除的数字个数比一半多,当前答案还比已经得到的最优解更优,那么更新最优解
                if(cnt << 1 >= n) ans = (*it).first;
            } while(it != fact.begin());
        }
        // CF推荐I64d输出long long
        printf("%I64d", ans);
        return 0;
    }
    
  • 相关阅读:
    平稳退化,JS和HTML标记分离,极致性能的JavaScript图片库
    简单选择排序(Simple Selection Sort)的C语言实现
    堆排序(Heap Sort)的C语言实现
    快速排序(Quick Sort)的C语言实现
    希尔排序(Shell's Sort)的C语言实现
    2-路插入排序(2-way Insertion Sort)的C语言实现
    折半插入排序(Binary Insertion Sort)的C语言实现
    直接插入排序(Straight Insertion Sort)的C语言实现
    栈的链式存储方法的C语言实现
    栈的顺序存储方式的C语言实现
  • 原文地址:https://www.cnblogs.com/winlere/p/10349132.html
Copyright © 2011-2022 走看看