The North American Invitational Programming Contest 2016 I-Tourists
LCA裸题
#include<bits/stdc++.h> using namespace std; #define ll long long #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r #define pb push_back const int INF=0x3f3f3f3f; const int N=2e5+10; vector<int>g[N]; vector<ll>edge[N]; int anc[20][N]; int deep[N]; ll h[N]; bool vis[N]= {false}; int s; void dfs(int o,int u,ll w) { if(o!=u)deep[u]=deep[o]+1,h[u]=h[o]+w; for(int j=0; j<g[u].size(); j++) { if(g[u][j]!=o) { anc[0][g[u][j]]=u; for(int i=1; i<20; i++)anc[i][g[u][j]]=anc[i-1][anc[i-1][g[u][j]]]; dfs(u,g[u][j],edge[u][j]); } } } int lca(int u,int v)//公共祖先 { if(deep[u]<deep[v])swap(u,v); for(int i=19; i>=0; i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u]; if(u==v)return u; for(int i=19; i>=0; i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v]; return anc[0][u]; } ll dis(int u,int v)//距离 { return h[u]+h[v]-2*h[lca(u,v)]; } void init() { for(int i=0; i<20; i++)anc[i][1]=1; dfs(0,1,1); } int main() { freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); int n,m,a,b; cin>>n; for(int i=0; i<n; ++i) { cin>>a>>b; g[a].pb(b); g[b].pb(a); edge[a].pb(1); edge[b].pb(1); } init(); ll ans=0; for(int i=1; i<=n; ++i) for(int j=i*2; j<=n; j+=i) { if(j%i==0) ans+=(dis(i,j)+1); } cout<<ans<<endl; return 0; }