You are on page 1of 6

import import import import import import import import import import import

java.util.Map; java.io.IOException; java.util.Arrays; java.util.HashMap; java.util.InputMismatchException; java.util.ArrayList; java.util.Set; java.io.OutputStream; java.io.PrintWriter; java.math.BigInteger; java.io.InputStream;

/** * Built using CHelper plug-in * Actual solution is at the top * @author karan173 */ public class Main implements Runnable{ public static void main(String[] args) { new Thread(null, new Main(), "karan", 1 << 24).start(); } public void run() { InputStream inputStream = System.in; OutputStream outputStream = System.out; FastReader in = new FastReader(inputStream); PrintWriter out = new PrintWriter(outputStream); primeDist solver = new primeDist(); try { solver.solve(1, in, out); } catch(StackOverflowError e) { return; } out.close(); } } class primeDist { long n; ArrayList<Integer> e[]; long netCnt = 0; //boolean visited[]; --> in a tree we dont need visited -> see dfs for a t ree public void solve(int testNumber, FastReader in, PrintWriter out) { sieve (50002); n = in.nextInt (); e = new ArrayList[(int) n]; maxDepth = new int[n]; for (int i = 0; i < n; i++) { e[i] = new ArrayList<Integer> ();

//

} for (int i = 0; i < n-1; i++) { int u = in.nextInt () - 1; int v = in.nextInt () - 1; e[u].add (v); e[v].add (u); } //thinking in terms of depth rather than height now dfs (0, -1, 0); double ans = netCnt; ans *= 2; ans /= (n * (n - 1)); out.println (ans); } private HashMap<Integer, Integer> dfs(int u, int par, int lvl) { HashMap<Integer, Integer> curDepth = new HashMap<Integer, Integer> (); //insert current node curDepth.put (lvl, 1); for (int v : e[u]) { if (v == par) { continue; } HashMap<Integer, Integer> childDepth = dfs (v, u, lvl + 1); //we perform weighted merges, so that each nodes array //is at most merged O(logn) times //to merge childDepth into Depth //i.e childDepth smaller if (childDepth.size () > curDepth.size ()) { HashMap<Integer, Integer> temp = childDepth; childDepth = curDepth; curDepth = temp; } boolean try1 = (curDepth.size ()+200 > primeCnt) ? (true) : (false); try1 = false; //update answer if (try1 == false) { for (Map.Entry<Integer, Integer> entry : childDepth.entrySet ()) { for (Map.Entry<Integer, Integer> entry2 : curDepth.entrySet ()) { int sum = entry.getKey () + entry2.getKey () - (lvl << 1 ); if (isSievePrime (sum)) { netCnt += ((long) entry.getValue ()) * entry2.getVal ue (); } } } } else

{ for (Map.Entry<Integer, Integer> entry : childDepth.entrySet ()) { if (try1) { int d1 = entry.getKey (); int firstPIndex = Arrays.binarySearch (primes, 0, primeC nt, d1 - lvl); if (firstPIndex < 0) { firstPIndex = -1 - firstPIndex; } //p is decr. d2 is decr for (int j = firstPIndex; j <= primeCnt - 1; j++) { int p = primes[j]; //for net distance to be p int d2 = (lvl * 2) + p - d1; if (d2 > n - 1) { break; } if (curDepth.containsKey (d2)) { long val1 = entry.getValue (); long val2 = curDepth.get (d2); netCnt += val1 * val2; } } } } } //merge smaller map into bigger finally for (Map.Entry<Integer, Integer> entry : childDepth.entrySet ()) { int d = entry.getKey (); if (curDepth.containsKey (d)) { curDepth.put (d, entry.getValue () + curDepth.get (d)); } else { curDepth.put (d, entry.getValue ()); } } } return curDepth; }

int primes[] = new int[5200]; int primeCnt = 0; public static boolean[] flags; public void sieve(int MAXN)

{ // note flags for even are not set flags = new boolean[MAXN + 1]; Arrays.fill (flags, true); flags[1] = false; primes[primeCnt++] = 2; int p, i; for (p = 3; p * p <= MAXN; p += 2) // dont traverse even { if (flags[p]) // prime { primes[primeCnt++] = p; // flags for all before p*p have been set // for (i = p * p; i < MAXN; i += p + p) { flags[i] = false; } } } // now we have written primes till sqrt(MAXN) so all non primes flags // have been set for (; p <= MAXN; p += 2) { if (flags[p]) // prime { primes[primeCnt++] = p; } } } public boolean isSievePrime(int n) { if (n == 2) { return true; } if (n % 2 == 0) { return false; } if (n < 2) { return false; } return flags[n]; } } class FastReader { private private private private private InputStream stream; byte[] buf = new byte[1024]; int curChar; int numChars; SpaceCharFilter filter;

public FastReader(InputStream stream) {

this.stream = stream; } public int read() { if (numChars == -1) { throw new InputMismatchException (); } if (curChar >= numChars) { curChar = 0; try { numChars = stream.read (buf); } catch (IOException e) { throw new InputMismatchException (); } if (numChars <= 0) { return -1; } } return buf[curChar++]; } public int nextInt() { int c = read (); while (isSpaceChar (c)) c = read (); int sgn = 1; if (c == '-') { sgn = -1; c = read (); } int res = 0; do { if (c < '0' || c > '9') { throw new InputMismatchException (); } res *= 10; res += c - '0'; c = read (); } while (!isSpaceChar (c)); return res * sgn; } public boolean isSpaceChar(int c) { if (filter != null) { return filter.isSpaceChar (c); } return isWhitespace (c); }

public static boolean isWhitespace(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; } public interface SpaceCharFilter { public boolean isSpaceChar(int ch); } }

You might also like