1. 程式人生 > >【The North American Invitational Programming Contest 2016 】I、Tourists

【The North American Invitational Programming Contest 2016 】I、Tourists

6000ms
262144K

In Tree City, there are nnn tourist attractions uniquely labeled 111 to nnn. The attractions are connected by a set of n−1n - 1n−1 bidirectional roads in such a way that a tourist can get from any attraction to any other using some path of roads.

You are a member of the Tree City planning committee. After much research into tourism, your committee has discovered a very interesting fact about tourists: they LOVE number theory! A tourist who visits an attraction with label xxx will then visit another attraction with label yyy if y>xy > xy>x and yyy is a multiple of xxx. Moreover, if the two attractions are not directly connected by a road the tourist will necessarily visit all of the attractions on the path connecting xxx and yyy, even if they aren’t multiples of xxx. The number of attractions visited includes xxx and yyy themselves. Call this the lengthlengthlength of a path.

Consider this city map:

Here are all the paths that tourists might take, with the lengths for each:

1→2=4,1→8=3,2→10=3,1→3=3,1 \rightarrow 2 = 4, 1 \rightarrow 8 = 3, 2 \rightarrow 10 = 3,1 \rightarrow 3 = 3, 1→2=4,1→8=3,2→10=3,1→3=3,

1→9=3,3→6=3,1→4=2,1→10=2,1 \rightarrow 9 = 3, 3 \rightarrow 6 = 3, 1 \rightarrow 4 = 2, 1 \rightarrow 10 = 2,1→9=3,3→6=3,1→4=2,1→10=2,

3→9=3,1→5=2,2→4=5,4→8=4,3 \rightarrow 9 = 3, 1 \rightarrow 5 = 2, 2 \rightarrow 4 = 5, 4 \rightarrow 8 = 4,3→9=3,1→5=2,2→4=5,4→8=4,

1→6=3,2→6=6,5→10=3,1→7=4,1 \rightarrow 6 = 3, 2 \rightarrow 6 = 6, 5 \rightarrow 10 = 3, 1 \rightarrow 7 = 4,1→6=3,2→6=6,5→10=3,1→7=4,2→8=2, 2 \rightarrow 8 = 2,2→8=2,

To take advantage of this phenomenon of tourist behavior, the committee would like to determine the number of attractions on paths from an attraction xxx to an attraction yyy such that y>xy > xy>x and yyy is a multiple of xxx. You are to compute the sum of the lengths of all such paths. For the example above, this is: 4+3+2+2+3+4+3+3+2+5+6+2+3+3+3+4+3=554 + 3 + 2 + 2 + 3 + 4 + 3 + 3 + 2 + 5 + 6 + 2 + 3 + 3 + 3 + 4 + 3 = 554+3+2+2+3+4+3+3+2+5+6+2+3+3+3+4+3=55.
Input

Each input will consist of a single test case. Note that your program may be run multiple times on different inputs. The first line of input will consist of an integer n(2≤n≤200,000)n (2 \le n \le 200,000)n(2≤n≤200,000) indicating the number of attractions. Each of the following n−1n-1n−1 lines will consist of a pair of space-separated integers iii and j(1≤i<j≤n)j (1 \le i < j \le n)j(1≤i<j≤n), denoting that attraction iii and attraction jjj are directly connected by a road. It is guaranteed that the set of attractions is connected.
Output

Output a single integer, which is the sum of the lengths of all paths between two attractions xxx and yyy such that y>xy > xy>x and yyy is a multiple of xxx.
樣例輸入

10
3 4
3 7
1 4
4 6
1 10
8 10
2 8
1 5
4 9

樣例輸出

55

直接利用倍增LCA求樹上兩點之間的距離,然後 O ( n ) s q r t ( n ) O(n)*sqrt(n) 求因子,複雜度大概為 O ( n ) s q r t ( n ) l o g ( n ) O(n)*sqrt(n)*log(n)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct yyy{
    ll t,
        nex;
}e[2*500001];
ll deepth[500001],fa[500001][22],lg[500001],head[500001];
ll tot;
void add(ll x,ll y) //鄰接表存樹
{
    e[++tot].t=y; 
    e[tot].nex=head[x];
    head[x]=tot;
}
void dfs(ll f,ll fath)
{
    deepth[f]=deepth[fath]+1;
    fa[f][0]=fath;
    for(ll i=1;(1<<i)<=deepth[f];i++)
      fa[f][i]=fa[fa[f][i-1]][i-1];
    for(ll i=head[f];i;i=e[i].nex)
      if(e[i].t!=fath)
        dfs(e[i].t,f);
}
ll lca(ll x,ll y)
{
    if(deepth[x]<deepth[y])
      swap(x,y);
    while(deepth[x]>deepth[y])
      x=fa[x][lg[deepth[x]-deepth[y]]-1];
    if(x==y)
      return x;
    for(ll k=lg[deepth[x]];k>=0;k--)
      if(fa[x][k]!=fa[y][k])
        x=fa[x][k], y=fa[y][k];
    return fa[x][0];
}
ll n,m,s,x,y;
int main()
{	ios::sync_with_stdio(0);
	cin.tie(0);
    cin>>n;
    for(ll i=1;i<=n-1;i++)
    {
        cin>>x>>y;
        add(x,y); add(y,x);
    }
    dfs(1,0);
    ll ans=0;
    for(ll i=1;i<=n;i++)
      lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    for(ll i=1;i<=n;i++){
    	for(ll j=i;j<=n;j+=i){
    		ans+=(deepth[i]-2*deepth[lca(i,j)]+deepth[j]+1);
		}
	}
	cout<<ans-n<<endl;
    return 0;
}