BZOJ 3837 [Pa2013]Filary

久未见 提交于 2020-01-22 18:19:30

Link
如果我们现在钦定了某一个数强制选,那么我们就是要选择最多的数使得它们的\(\gcd\ne1\)。这个可以在预处理完每个数的最小质因子之后检查每个质因子有多少个倍数即可。
可以发现\(k\ge\lceil\frac n2\rceil\),当\(m=2\)时可以直接取到。
因此我们钦定某个数,它出现在最优答案中的概率至少是\(\frac12\),随机\(t\)次之后正确率可以达到\(1-\frac1{2^t}\)

#include<cstdio>
#include<cctype>
#include<cstdlib>
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
int abs(int x){return x<0? -x:x;}
int gcd(int n,int m){return !n||!m? n+m:gcd(m,n%m);}
const int N=100007,M=10000007;
int pr[M>>3],f[M],a[N],t1[M],t2[M];
int main()
{
    int tot=0,n=read(),a1=0,a2=0;
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=2;i<=10000000;++i)
    {
    if(!f[i]) f[i]=pr[++tot]=i;
    for(int j=1;i*pr[j]<=10000000&&j<=tot;++j) if(f[i*pr[j]]=pr[j],!(i%pr[j])) break;
    }
    for(int T=10;T;--T)
    {
    int id=rand()%n+1,m=0;
    for(int i=1;i<=n;++i)
    {
        if(a[i]==a[id]) {++m;continue;}
        int x=abs(a[i]-a[id]),y=x,las=0;
        for(;x>1;las=f[x],x/=f[x]) if(f[x]^las) ++t1[f[x]],t2[f[x]]=gcd(y,t2[f[x]]);
    }
    for(int i=1;i<=n;++i)
    {
        if(a[id]==a[i]) continue;
        int x=abs(a[i]-a[id]);
        for(;x>1;t1[f[x]]=t2[f[x]]=0,x/=f[x]) if(t1[f[x]]+m>a1||(t1[f[x]]+m==a1&&t2[f[x]]>a2)) a1=t1[f[x]]+m,a2=t2[f[x]];
    }
    }
    printf("%d %d",a1,a2);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!