【Codeforces 364D】Ghd

給你nn個數,求一個儘量大的數,使得數列中有超過n2\frac{n}{2}個數能被該數整除。
ai1012a_i \leq 10^{12}


發現每一個數出現在能被整除的集合中的概率均12≥\frac{1}{2},於是考慮隨機。每一次猜測一個數在這個集合中,然後計算與其它數的gcd。最後查找一個最大的出現次數超過n2\frac{n}{2}的gcd即可。(若res[i]res[j]res[i]|res[j]sum[i]+=sum[j]sum[i]+=sum[j]
我們分析一下這樣做的正確率。每一次選對的概率12≥\frac{1}{2},所以說一次選錯的概率12\leq \frac{1}{2},即隨機xx次的成功率爲112x\Large 1-\frac{1}{2^x}。當xx取約1414時,其成功率可以接受。


        #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);
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章