BZOj2790/POI2012 Distance

Task
對於兩個正整數a、b,這樣定義函數d(a,b):每次操作可以選擇一個質數p,將a變成a*p或a/p,
如果選擇變成a/p就要保證p是a的約數,d(a,b)表示將a變成b所需的最少操作次數。例如d(69,42)=3。
現在給出n個正整數A1,A2,…,An,對於每個i (1<=i<=n),求最小的j(1<=j<=n)使得i≠j且d(Ai,Aj)最小。
2<=n<=100,000, Ai<=1,000,000.

Solution
設cnt[i]爲i的質因子個數,d(a,b)=cnt[a]-cnt[b]-2*cnt[gcd(a,b)],對於每個i,考慮枚舉A[i]與A[j]的gcd,假設爲k.剩下不確定的答案就是A[j]了,爲了讓cnt[A[j]]儘可能小,可以預處理出dp[k],表示k的倍數中cnt最小的下標t.爲了防止t=i,對於每個k,需要求出前兩小的下標.
Ai≤10^6,因子個數最多爲240個,可以直接暴力枚舉每個值的所有因子進行求解.

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define ll long long
#include<queue>
#include<set>
using namespace std;
inline void rd(int &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do res=(res<<1)+(res<<3)+(c^48);
    while(c=getchar(),c>=48);
}
inline void print(ll x){
    if(!x)return ;
    print(x/10);
    putchar((x%10)^48);
}
inline void sc(ll x){
    if(x<0){x=-x;putchar('-');}
    print(x);
    if(!x)putchar('0');
    putchar('\n');
}
inline void Max(int &x,int y){if(x<y)x=y;}
inline void Min(int &x,int y){if(x>y)x=y;}
const int M=1e6+5;
const int N=1e5+5;
int mark[M],son[M][10],cnt[M][10],A[N],mx=0;
vector<int>rec[M];
struct node{
    int v,id;
    node(){id=-1,v=-1;}
    bool operator<(const node &tmp)const{
        if(tmp.v!=v)return v<tmp.v;
        return id<tmp.id;
    }
}h[M][2],ans[N];
void Init(){
    for(int i=2;i*i<=mx;i++){
        if(!mark[i]){
            for(int j=i;j<=mx;j+=i){
                son[j][++son[j][0]]=i;
                mark[j]=1;
            }
        }
    }
}
void Up(int x,node y){//y是x的倍數    
//  if(h[x][0].id==-1)h[x][0]=y;
    if(h[x][0].id==-1||y<h[x][0]){
        h[x][1]=h[x][0];
        h[x][0]=y;
    }
    else if(h[x][1].id==-1||y<h[x][1]){
        h[x][1]=y;
    }
}
void dfs(int id,int x,int p,int num){
    if(p==son[x][0]+1){
        node y;
        y=h[num][0];
        if(h[num][0].id==id)y=h[num][1];
        if(~y.v){
            y.v+=cnt[x][0]-2*cnt[num][0];
            if(ans[id].id==-1||y<ans[id])ans[id]=y;
        }
        return;
    }
    for(int i=0;i<=cnt[x][p];i++){
        dfs(id,x,p+1,num);
        num*=son[x][p];
    }
}
int main(){
    int n,i,j,cas,a,b,k;
    rd(n);
    for(i=1;i<=n;i++){
        rd(A[i]);Max(mx,A[i]);
        rec[A[i]].push_back(i);
    }
    Init();
    for(i=2;i<=mx;i++){
        int x=i;
        for(j=1;j<=son[i][0];j++){
            a=0;
            while(x%son[i][j]==0){a++;x/=son[i][j];}
            cnt[i][j]=a;
            cnt[i][0]+=a;
        }
        if(x!=1){
            son[i][++son[i][0]]=x;
            cnt[i][son[i][0]]=1;
            cnt[i][0]++;
        }
    }
    for(i=1;i<=mx;i++){
        for(j=i;j<=mx;j+=i){
            if(!rec[j].size())continue;
            node y;
            y.v=cnt[j][0];
            for(k=0;k<rec[j].size();k++){
                y.id=rec[j][k];
                Up(i,y);
            }
        }   
    }
    for(i=1;i<=n;i++)dfs(i,A[i],1,1);
    for(i=1;i<=n;i++)sc(ans[i].id);
    return 0;
}
發佈了39 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章