• 【题解】[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;
    }
    
  • 相关阅读:
    真正的e时代
    在线手册
    UVA 10616 Divisible Group Sums
    UVA 10721 Bar Codes
    UVA 10205 Stack 'em Up
    UVA 10247 Complete Tree Labeling
    UVA 10081 Tight Words
    UVA 11125 Arrange Some Marbles
    UVA 10128 Queue
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/winlere/p/10349132.html
Copyright © 2020-2023  润新知