【Codeforces 364D】Ghd

给你 n n n个数,求一个尽量大的数,使得数列中有超过 n 2 \frac{n}{2} 2n个数能被该数整除。
a i ≤ 1 0 12 a_i \leq 10^{12} ai1012


发现每一个数出现在能被整除的集合中的概率均 ≥ 1 2 ≥\frac{1}{2} 21,于是考虑随机。每一次猜测一个数在这个集合中,然后计算与其它数的gcd。最后查找一个最大的出现次数超过 n 2 \frac{n}{2} 2n的gcd即可。(若 r e s [ i ] ∣ r e s [ j ] res[i]|res[j] res[i]res[j] s u m [ i ] + = s u m [ j ] sum[i]+=sum[j] sum[i]+=sum[j]
我们分析一下这样做的正确率。每一次选对的概率 ≥ 1 2 ≥\frac{1}{2} 21,所以说一次选错的概率 ≤ 1 2 \leq \frac{1}{2} 21,即随机 x x x次的成功率为 1 − 1 2 x \Large 1-\frac{1}{2^x} 12x1。当 x x x取约 14 14 14时,其成功率可以接受。


        #include<bits/stdc++.h>
        #define reg register
        #define ll long long
        using namespace std;
        const int mn = 1000005;
        ll a[mn], res[mn];
        int sum[mn];
        inline ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
        int main()
        {
            srand(time(NULL));
            int n;
            scanf("%d", &n);
            for(int i = 1; i <= n; i++)
                scanf("%I64d", &a[i]);
            ll ans = 1;
            for(int T = 0; T < 13; T++)
            {
                int pos = ((rand() << 15) + rand()) % n + 1;
                if(a[pos] <= ans) continue;
                ll maxs = 1;
                for(reg int i = 1; i <= n; i++)
                    res[i] = gcd(a[i], a[pos]), maxs = max(res[i], maxs);
                if(maxs <= ans) continue;
                sort(res + 1, res + 1 + n); int cnt = 0;
                for(reg int i = 1; i <= n; i++)
                {
                    if(res[i] != res[i - 1])
                        res[++cnt] = res[i], sum[cnt] = 0;
                    ++sum[cnt];
                }
                for(reg int i = cnt; i; i--)
                {
                    if(ans >= res[i]) break;
                    int tmp = 0;
                    for(int j = i; j <= cnt; j++)
                        if(res[j] % res[i] == 0) tmp += sum[j];
                    if((tmp << 1) >= n) {ans = res[i]; break;}
                }
            }
            printf("%I64d\n", ans);
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值