BZOJ2790 : [Poi2012]Distance
设b[i]为将i分解质因数后所有质数的指数和,则$d(i,j)=b[i]+b[j]-2b[\gcd(i,j)]$。
设d[i]为i的倍数中的最优解和次优解。
对于i,枚举它的约数k作为gcd,然后用d[k]去更新ans[i]即可。
时间复杂度$O(n\log n)$。
#include<cstdio> #define N 1000001 int n,m,i,j,p[N],tot,b[N],a[N];bool v[N]; struct P{ int x0,y0,x1,y1; P(){x0=x1=N;} inline void up(int x,int y){ if(x<x0||x==x0&&y<=y0){ if(y!=y0)x1=x0,y1=y0; x0=x,y0=y; }else if(y!=y0&&(x<x1||x==x1&&y<y1))x1=x,y1=y; } }d[N],f[N],c[N]; inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} int main(){ for(read(n),i=1;i<=n;i++){ read(a[i]),c[a[i]].up(i,i); if(m<a[i])m=a[i]; } for(i=2;i<=m;i++){ if(!v[i])p[++tot]=i,b[i]=1; for(j=1;j<=tot;j++){ if(i*p[j]>m)break; v[i*p[j]]=1,b[i*p[j]]=b[i]+1; if(i%p[j]==0)break; } } for(i=1;i<=m;i++)for(j=i;j<=m;j+=i){ if(c[j].x0<N)d[i].up(b[j],c[j].x0); if(c[j].x1<N)d[i].up(b[j],c[j].x1); } for(i=1;i<=m;i++)if(d[i].x0<N)for(j=i;j<=m;j+=i)if(c[j].x0<N){ f[j].up(b[j]+d[i].x0-2*b[i],d[i].y0); f[j].up(b[j]+d[i].x1-2*b[i],d[i].y1); } for(i=1;i<=n;i++)printf("%d\n",f[a[i]].y0==i?f[a[i]].y1:f[a[i]].y0); return 0; }