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;
}

  

posted @ 2015-08-13 22:54  Claris  阅读(383)  评论(0编辑  收藏  举报