BZOJ3837 [Pa2013]Filary

Link
如果我们现在钦定了某一个数强制选,那么我们就是要选择最多的数使得它们的(gcd e1)。这个可以在预处理完每个数的最小质因子之后检查每个质因子有多少个倍数即可。
可以发现(kgelceilfrac n2 ceil),当(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);
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12229092.html