#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;
}