#pragma warning(disable:4786) //#pragma comment(linker, "/STACK:16777216") #pragma comment(linker, "/STACK:1073741824") #include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<set> #include<map> #include<functional> #include<string> #include<cstring> #include<cstdlib> #include<queue> #include<utility> #include<fstream> #include<sstream> #include<cmath> #include<stack> #include<assert.h> #include<complex> #include<bitset> using namespace std; #define MEM(a, b) memset(a, (b), sizeof(a)) #define CLR(a) memset(a, 0, sizeof(a)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define ABS(X) ( (X) > 0 ? (X) : ( -(X) ) ) #define S(X) ( (X) * (X) ) #define SZ(V) (int )V.size() #define FORN(i, n) for(i = 0; i < n; i++) #define FORAB(i, a, b) for(i = a; i <= b; i++) #define ALL(V) V.begin(), V.end() typedef pair<int,int> PII; typedef pair<double, double> PDD; typedef vector<int> VI; #define IN(A, B, C) assert( B <= A && A <= C) //typedef int LL; //typedef __int64 LL; vector<int> Prime; int mark[50002]; void sieve(int n) { int i,j,limit=sqrt(n*1.)+2; mark[1] = 1; for(i=4;i<=n;i+=2) mark[i]=1; Prime.push_back(2); for(i=3;i<=n;i+=2) if(!mark[i]) { Prime.push_back(i); if(i<=limit) { for(j=i*i;j<=n;j+=i*2) { mark[j] = 1; } } } } VI V[200003]; vector<PII> E[200003]; int n, ans, dummy; vector<int>::iterator iV; int xx; void Binarize(int at, int parent) { int x, y, sz, i; sz = V[at].size(); // printf("%d %d\n", xx++, sz); if(parent) { E[at].push_back(PII(parent, at<=n)); } if(sz <= 2) { for(i = 0; i < sz; i++) { if(at <= n) V[V[at][i]].erase( find(V[V[at][i]].begin(), V[V[at][i]].end(), at) ); E[at].push_back(PII(V[at][i], 1)); Binarize(V[at][i], at); } } else { x = dummy + 1; y = dummy + 2; dummy += 2; for(i = 0; i < sz; i++) { if(i < sz/2) V[x].push_back(V[at][i]); else V[y].push_back(V[at][i]); if(at <= n) V[V[at][i]].erase( find(V[V[at][i]].begin(), V[V[at][i]].end(), at) ); } E[at].push_back( PII(x, 0) ); E[at].push_back( PII(y, 0) ); Binarize(x, at); Binarize(y, at); } } int subtree[200005], best_pos, best_value, best_d; int parent[200005], _sz; int DFS(int at, int parent) { subtree[at] = 1; ::parent[at] = parent; int here, sz = E[at].size(), i; for(i = 0; i < sz; i++) { if(E[at][i].first == parent) { here = E[at][i].second; continue; } subtree[at] += DFS(E[at][i].first, at); } if(parent && (best_pos == -1 || best_value > ABS(_sz/2 - subtree[at]))) { best_pos = at, best_value = ABS(_sz/2 - subtree[at]), best_d = here; } return subtree[at]; } void populate_depth(int at, int depth, int parent, vector<int> &V) { if(at <= n) V.push_back(depth); int i, sz = E[at].size(); for(i = 0; i < sz; i++) { if(E[at][i].first == parent) continue; populate_depth(E[at][i].first, depth + E[at][i].second, at, V); } } typedef complex<double> base; double PI = acos(-1.); void fft (vector<base> & a, bool invert) { int n = (int) a.size(); for (int i=1, j=0; i<n; ++i) { int bit = n >> 1; for (; j>=bit; bit>>=1) j -= bit; j += bit; if (i < j) swap (a[i], a[j]); } for (int len=2; len<=n; len<<=1) { double ang = 2*PI/len * (invert ? -1 : 1); base wlen (cos(ang), sin(ang)); for (int i=0; i<n; i+=len) { base w (1); for (int j=0; j<len/2; ++j) { base u = a[i+j], v = a[i+j+len/2] * w; a[i+j] = u + v; a[i+j+len/2] = u - v; w *= wlen; } } } if (invert) for (int i=0; i<n; ++i) a[i] /= n; } void multiply (const vector<int> & a, const vector<int> & b, vector<int> & res) { vector<base> fa, fb; int i; int sz = a.size(); for(i = 0; i < sz; i++) fa.push_back( a[i] ); sz = b.size(); for(i = 0; i < sz; i++) fb.push_back( b[i] ); size_t n = 1; while (n < MAX (a.size(), b.size())) n <<= 1; n <<= 1; fa.resize (n), fb.resize (n); fft (fa, false), fft (fb, false); for (i=0; i<n; ++i) fa[i] *= fb[i]; fft (fa, true); res.resize (n); for (i=0; i<n; ++i) res[i] = int (fa[i].real() + 0.5); } void f(vector<int> &X, vector<int> &Y) { int i, maxx = 0; for(i = X.size() - 1; i >= 0; i--) maxx = MAX(X[i], maxx); for(i = Y.size() - 1; i >= 0; i--) maxx = MAX(Y[i], maxx); vector<int> A(maxx + 1, 0), B(maxx + 1, 0), C; for(i = X.size() - 1; i >= 0; i--) A[X[i]]++; for(i = Y.size() - 1; i >= 0; i--) B[Y[i]]++; // printf(">>>>\n"); // for(i = A.size() - 1; i >= 0; i--) printf("%d, ", A[i]); printf("\n"); // for(i = B.size() - 1; i >= 0; i--) printf("%d, ", B[i]); printf("\n"); multiply(A, B, C); // for(i = C.size() - 1; i >= 0; i--) printf("%d, ", C[i]); printf("\n"); maxx = C.size(); int sz = Prime.size(); for(i = 0; i < sz && Prime[i] < maxx; i++) ans += C[Prime[i]]; } queue<PII> Q; void isTree() { queue<int> Q; int vis[50004]; int u, i; MEM(vis, 0); vis[1] = 1; Q.push(1); while(!Q.empty()) { u = Q.front(); Q.pop(); for(i = V[u].size() - 1; i >= 0; i--) if(vis[V[u][i]]==0) { vis[V[u][i]] = 1; Q.push( V[u][i] ); } } for(i = 1; i <= n; i++) assert(vis[i]); } int main() { int i, a, b, j; PII u; vector<int> X, Y; sieve(50002); scanf("%d", &n); IN(n, 2, 50000); for(i = 1; i < n; i++) { scanf("%d %d", &a, &b); IN(a, 1, n); IN(b, 1, n); V[a].push_back(b); V[b].push_back(a); } isTree(); dummy = n; //Make the tree binary. If there is a node with many children, keep one child left and make other children //the children of the right node. make the cost to right child 0. other 1. //In this tree, the cost of the path from an original node to another original node is same. Binarize(1, 0); /* printf("%d\n", ans); for(i = 1; i <= dummy; i++) { printf("%d:", i); for(j = 0; j < E[i].size(); j++) printf(" (%d, %d)", E[i][j].first, E[i][j].second); printf("\n"); } */ //Now find center of the tree. center of the tree is a node, having <=n/3 nodes in each subtree if //this node is deleted. //Now delete the link to its parent. For each subtree solve recursively. //For inter subtree path, list up all the distances to the original nodes in each subtree. Find the solution using FFT int x, y; int dd = 0; Q.push( PII(1, dummy) ); while(!Q.empty()) { u = Q.front(); Q.pop(); _sz = u.second; if(_sz == 1) continue; best_pos = -1; best_value = u.second; DFS(u.first, 0); x = best_pos; y = parent[x]; E[x].erase( find(E[x].begin(), E[x].end(), PII(y, best_d)) ); E[y].erase( find(E[y].begin(), E[y].end(), PII(x, best_d)) ); Q.push( PII(x, subtree[x]) ); Q.push( PII(y, _sz - subtree[x]) ); X.clear(); Y.clear(); populate_depth(x, 0, 0, X); populate_depth(y, 0, 0, Y); if(best_d) for(i = X.size() - 1; i >= 0; i--) X[i]++; f(X, Y); } // printf("%d\n", ans); double f = (1.*ans)/( (n*(n-1.))/2 ); printf("%.12lf\n", f); return 0; }