1. 程式人生 > >CF364D Ghd(隨機化)

CF364D Ghd(隨機化)

另一個集合\(s\)\(ghd\)\(max\{gcd(s')||s'|>=0.5|s|\}\) 給定序列\(a\),求\(ghd\)

隨機化演算法。因為\(|s'|\geq 0.5|S|\),所以每個元素在\(s'\)中的概率為\(0.5\),我們可以欽定一個元素令它在\(s'\)中,那麼算出它和其他所有元素的\(\gcd\),用\(map\)將所有的\(\gcd\)存起來,\(first\)存值,\(second\)存這個值的出現次數。然後從大到小列舉每一個\(\gcd\),並把比它大的那些且是它倍數的\(\gcd\)的出現次數加起來,如果某一次某個\(\gcd\)出現次數大於一半,那麼該答案可行

為了避免TLE加幾發剪枝,比如如果隨機出來的元素比最優答案小就無視,如果兩個數的\(\gcd\)比最優答案小無視,從大到小列舉元素只要有一個答案成立剩下的全都可以無視。然後\(rand\)\(15\)次左右基本就能出答案了

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fi first
#define se second
#define IT map<ll,int>::iterator
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
ll read(){
    R ll res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e6+5;
ll a[N],ans=1,x;int n,pos;map<ll,int>mp;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int main(){
//  freopen("testdata.in","r",stdin);
    srand(time(0));
    n=read();
    fp(i,1,n)a[i]=read();
    fp(T,1,15){
        pos=(1ll*rand()*RAND_MAX+rand())%n+1;
        if(a[pos]<=ans)continue;
        fp(i,1,n){
            x=gcd(a[pos],a[i]);if(x<=ans)continue;
            mp.count(x)?++mp[x]:mp[x]=1;
        }if(mp.empty())continue;
        IT it=mp.end();
        do{
            --it;if(it->fi<=ans)break;
            int cnt=0;
            for(IT itl=it;itl!=mp.end()&&(cnt<<1)<n;++itl)
                if(itl->fi%it->fi==0)cnt+=itl->se;
            if((cnt<<1)>=n){ans=it->fi;break;}
        }while(it!=mp.begin());
        map<ll,int>().swap(mp);
    }printf("%I64d\n",ans);
    return 0;
}