【题解】[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;
}
原文地址:https://www.cnblogs.com/winlere/p/10349132.html