省選專練之GCD生成樹
阿新 • • 發佈:2018-11-02
非常著名的一道經典題。
考慮一個性質:如果兩個點GCD相同必然更優。
於是我們有了一些點權互不相同的點。
發現點權並不大,從大到小列舉點權。
用並查集維護聯通性。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline void read(int &x){ x=0; int f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } x*=f; } const int N=1e6+10; int T[N]; int fa[N]; inline int getfa(int x){ if(fa[x]==x)return x; else return fa[x]=getfa(fa[x]); } int n; int val[N]; int Mx; int ans=0; int main(){ read(n); for(int i=1;i<=n;++i){ read(val[i]); Mx=max(Mx,val[i]); if(T[val[i]])ans+=val[i]; else T[val[i]]=fa[i]=i; } for(int i=Mx;i>=1;--i){ int now=0; for(int j=1;j*i<=Mx;++j){ if(T[i*j]){ if(!now)now=T[i*j]; else{ if(getfa(now)==getfa(T[i*j]))continue; else{ fa[getfa(now)]=getfa(T[i*j]); ans+=i; } } } } } cout<<ans; }