#include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <cstdlib> #include <complex> #include <string> #include <vector> #include <cstdio> #include <cmath> //#include <ctime> #include <map> using namespace std; // FFT on complex filed. (You can also use FFT on finite field.) complex <double> x[1<<20]; complex <double> y[1<<20]; complex <double> r[1<<20]; namespace Fourier { // n must be 2^k complex <double> t[1<<20]; void FFT(complex <double> *array, int n, double pi = M_PI) { for(int step = n>>1; step >= 1; step >>= 1) { complex <double> w(cos(2 * pi * step / n), sin(2 * pi * step / n)); for(int start = 0; start < step; start ++) { complex <double> factor(1, 0); int z = 0; for(int i = start; i < n; i += step << 1) { array[i+step] *= factor; array[i] += array[i+step]; array[i+step] = array[i] - array[i+step] - array[i+step]; factor *= w; t[z] = array[i]; t[z+n/step/2] = array[i+step]; z ++; } z = 0; for(int i = start; i < n; i += step) array[i] = t[z++]; } } for(int i = 0; i < n; i++) array[i] *= complex <double> (1/sqrt(n), 0); } void IFFT(complex <double> *array, int n) { FFT(array, n, -M_PI); } void cyclic_convolution(complex <double> *A, complex <double> *B, complex <double> *result, int n) { FFT(A, n); FFT(B, n); for(int i = 0; i < n; i++) result[i] = A[i] * B[i]; IFFT(result, n); for(int i = 0; i < n; i++) result[i] *= complex <double> (sqrt(n), 0); } } int n; const int MAXN = 200000; const int MAXDEPTH = 20; vector <int> e[MAXN]; int cntNodes[MAXN]; int minValue, center; vector <int> cache[MAXDEPTH][4]; int cache_ans[MAXDEPTH][4][MAXN]; int ans[MAXN]; int temp1[MAXN]; int temp2[MAXN]; int temp3[MAXN]; int temp[MAXN]; int saveN[MAXDEPTH]; // find the minimal n such that 2**n > x int minimalPow2(int x) { int ret = 0; int t = 1; while(t < x) { ret ++; t = t + t; } return ret; } // use dfs to find the center of a tree int dfs(int cur, int from, int d, int n, bool special = false, int depth = -1) { if(special) cache_ans[depth][0][d] ++; cntNodes[cur] = 1; int maxSubTree = 0, cnt = 0; for(int i = 0; i < e[cur].size(); i++) if(e[cur][i] != from) { int t = dfs(e[cur][i], cur, d+1, n, special, depth); cntNodes[cur] += cntNodes[e[cur][i]]; cnt += t; maxSubTree = max(maxSubTree, t); } maxSubTree = max(maxSubTree, n-1-cnt); if(n > 0 && maxSubTree < minValue) { center = cur; minValue = maxSubTree; } return cnt + 1; } int totNodes; int findCenter(int root, int depth) { int n = dfs(root, -1, 0, 0, true, depth); minValue = 100000000; totNodes = dfs(root, -1, 0, n, false, depth); dfs(center, -1, 0, n, false, depth); return center; } // A[i]: number of nodes have a distance i from subtree A // B[i]: number of nodes have a distance i from subtree B // Update all pathes between subtree A and subtree B void calcPair(int *A, int *B, int N) { for(int i = 0; i < (1<<N); i++) { x[i] = complex <double> (A[i], 0); y[i] = complex <double> (B[i], 0); } Fourier :: cyclic_convolution(x, y, r, 1<<N); for(int i = 1; i < (1<<N); i++) ans[i] += (long long)(r[i].real() + 0.5); } void solve(int root, int depth, int reqN) { for(int i = 0; i < (1<<reqN); i++) { cache_ans[depth][0][i] = 0; cache_ans[depth][1][i] = 0; cache_ans[depth][2][i] = 0; cache_ans[depth][3][i] = 0; } int center = findCenter(root, depth); int totalNodes = cntNodes[center]; cache_ans[depth][0][0] = 1; if(totalNodes <= 2) { if(totalNodes == 2) { cache_ans[depth][0][1] = 1; ans[1] ++; } return; } cache[depth][0] = e[center]; cache[depth][1].clear(), cache[depth][2].clear(), cache[depth][3].clear(); int cnt = 1; // The subtree will be grouped into 3 parts, each one has a size no more than N/2. for(int i = 0; i < e[center].size(); i++) { int before = cnt; int after = cnt + cntNodes[e[center][i]]; cnt = after; if(after <= totalNodes / 2) cache[depth][1].push_back(e[center][i]); else if(before <= totalNodes / 2) cache[depth][2].push_back(e[center][i]); else cache[depth][3].push_back(e[center][i]); } int N = minimalPow2(totalNodes); N = max(N, 2); e[center] = cache[depth][1]; solve(center, depth + 1, N); for(int i = 1; i < (1<<N); i++) cache_ans[depth][1][i] = cache_ans[depth+1][0][i]; e[center] = cache[depth][2]; solve(center, depth + 1, N); for(int i = 1; i < (1<<N); i++) cache_ans[depth][2][i] = cache_ans[depth+1][0][i]; e[center] = cache[depth][3]; solve(center, depth + 1, N); for(int i = 1; i < (1<<N); i++) cache_ans[depth][3][i] = cache_ans[depth+1][0][i]; e[center] = cache[depth][0]; for(int i = 0; i < (1<<reqN); i++) { temp1[i] = cache_ans[depth][1][i]; temp2[i] = cache_ans[depth][2][i]; temp3[i] = cache_ans[depth][3][i]; } calcPair(temp1, temp2, reqN); calcPair(temp1, temp3, reqN); calcPair(temp2, temp3, reqN); } bool isPrime[1000001]; int MAIN() { memset(isPrime, true, sizeof(isPrime)); isPrime[0] = isPrime[1] = false; for(int i = 2; i <= 1000000; i++) if(isPrime[i]) for(int j = i+i; j <= 1000000; j+=i) isPrime[j] = false; memset(ans, 0, sizeof(ans)); memset(cache_ans, 0, sizeof(cache_ans)); cin >> n; for(int i = 1; i < n; i++) { int a, b; cin >> a >> b; e[a].push_back(b); e[b].push_back(a); } solve(1, 0, minimalPow2(n)); double total = 0, sum = 0; for(int i = 1; i <= n; i++) { total += ans[i]; if(isPrime[i]) sum += ans[i]; } cout << sum / total << endl; return 0; } int main() { //srand((unsigned)time(NULL)); #ifdef LOCAL_TEST freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif ios :: sync_with_stdio(false); cout << fixed << setprecision(16); return MAIN(); }