bzoj 2790 [Poi2012]Distance 数学

来源:互联网 发布:东北财经大学会计 知乎 编辑:程序博客网 时间:2024/05/17 04:23

设d[i]为i的质因子个数(相同算多个)。那么i和j的答案就是d[a[i]gcd(a[i],a[j])]+d[a[j]gcd(a[i],a[j])]
然后枚举gcd,对于有当前枚举的gcd的因子的数,维护这些数d[a[i]gcd] 的最小值和次小值。更新一下这些数的答案。
时间复杂度O(n106)

#include <bits/stdc++.h>using namespace std;#define N 1100000int n,cnt,mx;vector<int>v[N];int a[N],d[N],ip[N],prime[N];int ans[N],val[N];void init(){    for(int i=2;i<=mx;i++)    {        if(!ip[i])prime[++cnt]=i,d[i]=1;        for(int j=1;j<=cnt&&i*prime[j]<=mx;j++)        {            ip[i*prime[j]]=1;            d[i*prime[j]]=d[i]+1;            if(i%prime[j]==0)break;        }    }}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]),mx=max(mx,a[i]);    memset(val,0x3f,sizeof(val));    init();    for(int i=1;i<=n;i++)        for(int j=1;j*j<=a[i];j++)            if(a[i]%j==0)            {                v[j].push_back(i);                if(j*j!=a[i])v[a[i]/j].push_back(i);            }    for(int i=1;i<=mx;i++)    {        int m=v[i].size();        if(m<=1)continue;        int ma,sa,mv=1<<30,sv=1<<30;        for(int j=0;j<m;j++)        {            int t=v[i][j],t1=d[a[t]/i];            if(t1<mv||(t1==mv&&ma>t))                sa=ma,sv=mv,ma=t,mv=t1;            else if(t1<sv||(t1==sv&&sa>t))                sa=t,sv=t1;        }        for(int j=0;j<m;j++)        {            int t=v[i][j],t1=d[a[t]/i];            if(t==ma)            {                if(val[t]>t1+sv||(val[t]==t1+sv&&ans[t]>sa))                    val[t]=t1+sv,ans[t]=sa;            }            else if(val[t]>t1+mv||(val[t]==t1+mv&&ans[t]>ma))                val[t]=t1+mv,ans[t]=ma;        }    }    for(int i=1;i<=n;i++)        printf("%d\n",ans[i]);    return 0;}
0 0
原创粉丝点击