public class Euler564 {
    static class Counts {
        int[] excess;
        int usedParts = 0;
        int maxLen = 1;

        Counts(int size) {
            excess = new int[size];
        }
    }

    static class EvalContext {
        int n;
        int E;
        double logTotal;
        double[] logfact;
    }

    static double evalPartition(Counts cnt, EvalContext ctx, int c1) {
        int n = ctx.n;
        int maxLen = cnt.maxLen;
        int perimeter = 2 * n - 3;

        double logw = ctx.logfact[n] - ctx.logfact[c1];
        for (int r = 1; r <= ctx.E; r++) {
            int c = cnt.excess[r];
            if (c > 0)
                logw -= ctx.logfact[c];
        }
        double prob = Math.exp(logw - ctx.logTotal);
        double pi = Math.PI;

        double low = 0.5 * maxLen;

        double twoRLow = 2.0 * low;
        double fourR2Low = 4.0 * low * low;
        double sumAlphaLow = 0.0;
        if (c1 > 0) {
            double l = 1.0;
            sumAlphaLow += c1 * Math.asin(l / twoRLow);
        }
        for (int r = 1; r <= ctx.E; r++) {
            int c = cnt.excess[r];
            if (c > 0) {
                double l = (double) (r + 1);
                sumAlphaLow += c * Math.asin(l / twoRLow);
            }
        }

        boolean minorExists = (sumAlphaLow >= pi - 1e-15);
        boolean useMajor = !minorExists;

        double[] sums = new double[4];
        double R = low;

        if (!useMajor) {
            if (Math.abs(sumAlphaLow - pi) > 1e-15) {
                double lo = low;
                double hi = Math.max(low * 2.0, perimeter / (2.0 * pi));
                for (int it = 0; it < 200; it++) {
                    computeSumsAt(hi, cnt, ctx, c1, sums);
                    double f = sums[0] - pi;
                    if (f < 0)
                        break;
                    hi *= 2.0;
                }
                R = 0.5 * (lo + hi);
                for (int it = 0; it < 60; it++) {
                    computeSumsAt(R, cnt, ctx, c1, sums);
                    double f = sums[0] - pi;
                    double fp = sums[1];
                    if (Math.abs(f) < 1e-14)
                        break;
                    double Rn = R - f / fp;
                    if (!(Rn > lo && Rn < hi) || !Double.isFinite(Rn))
                        Rn = 0.5 * (lo + hi);
                    computeSumsAt(Rn, cnt, ctx, c1, sums);
                    double fn = sums[0] - pi;
                    if (fn > 0)
                        lo = Rn;
                    else
                        hi = Rn;
                    R = Rn;
                }
            }
        } else {
            double lo = low;
            double hi = Math.max(low * 2.0, perimeter / (2.0 * pi));
            for (int it = 0; it < 200; it++) {
                computeSumsAt(hi, cnt, ctx, c1, sums);
                double f = sums[0] - 2.0 * sums[2];
                if (f > 0)
                    break;
                hi *= 2.0;
            }
            R = 0.5 * (lo + hi);
            for (int it = 0; it < 60; it++) {
                computeSumsAt(R, cnt, ctx, c1, sums);
                double f = sums[0] - 2.0 * sums[2];
                double fp = sums[1] - 2.0 * sums[3];
                if (Math.abs(f) < 1e-14)
                    break;
                double Rn = R - f / fp;
                if (!(Rn > lo && Rn < hi) || !Double.isFinite(Rn))
                    Rn = 0.5 * (lo + hi);
                computeSumsAt(Rn, cnt, ctx, c1, sums);
                double fn = sums[0] - 2.0 * sums[2];
                if (fn < 0)
                    lo = Rn;
                else
                    hi = Rn;
                R = Rn;
            }
        }

        double fourR2 = 4.0 * R * R;
        double areaSum = 0.0;
        double contribMax = 0.0;

        if (c1 > 0) {
            double l = 1.0;
            areaSum += c1 * (l * 0.25) * Math.sqrt(fourR2 - l * l);
        }
        for (int r = 1; r <= ctx.E; r++) {
            int c = cnt.excess[r];
            if (c > 0) {
                double l = (double) (r + 1);
                double contrib = (l * 0.25) * Math.sqrt(fourR2 - l * l);
                areaSum += c * contrib;
                if (r + 1 == maxLen)
                    contribMax = contrib;
            }
        }

        double area = useMajor ? Math.abs(areaSum - 2.0 * contribMax) : areaSum;
        return prob * area;
    }

    static void computeSumsAt(double R, Counts cnt, EvalContext ctx, int c1, double[] out) {
        double twoR = 2.0 * R;
        double fourR2 = 4.0 * R * R;
        double sumAlpha = 0.0;
        double sumDalpha = 0.0;
        double alphaMax = 0.0;
        double dalphaMax = 0.0;

        if (c1 > 0) {
            double l = 1.0;
            double s = Math.sqrt(fourR2 - l * l);
            double a = Math.asin(l / twoR);
            double da = -(l / (R * s));
            sumAlpha += c1 * a;
            sumDalpha += c1 * da;
        }

        for (int r = 1; r <= ctx.E; r++) {
            int c = cnt.excess[r];
            if (c > 0) {
                double l = (double) (r + 1);
                double s = Math.sqrt(fourR2 - l * l);
                double a = Math.asin(l / twoR);
                double da = -(l / (R * s));
                sumAlpha += c * a;
                sumDalpha += c * da;
                if (r + 1 == cnt.maxLen) {
                    alphaMax = a;
                    dalphaMax = da;
                }
            }
        }

        out[0] = sumAlpha;
        out[1] = sumDalpha;
        out[2] = alphaMax;
        out[3] = dalphaMax;
    }

    static double expectedArea = 0.0;

    static void rec(int maxPart, int remaining, Counts cnt, EvalContext ctx) {
        if (remaining == 0) {
            expectedArea += evalPartition(cnt, ctx, ctx.n - cnt.usedParts);
            return;
        }
        for (int part = Math.min(maxPart, remaining); part >= 1; part--) {
            cnt.excess[part]++;
            cnt.usedParts++;
            int oldMax = cnt.maxLen;
            cnt.maxLen = Math.max(cnt.maxLen, part + 1);

            rec(part, remaining - part, cnt, ctx);

            cnt.excess[part]--;
            cnt.usedParts--;
            if (cnt.excess[part] == 0 && cnt.maxLen == part + 1) {
                int ml = 1;
                for (int r = 1; r <= ctx.E; r++) {
                    if (cnt.excess[r] > 0)
                        ml = Math.max(ml, r + 1);
                }
                cnt.maxLen = ml;
            } else {
                cnt.maxLen = oldMax;
            }
        }
    }

    static double EofN(int n, double[] logfact) {
        int E = n - 3;
        int m = 2 * n - 4;
        double logTotal = logfact[m] - logfact[n - 1] - logfact[n - 3];

        Counts cnt = new Counts(E + 1);
        EvalContext ctx = new EvalContext();
        ctx.n = n;
        ctx.E = E;
        ctx.logTotal = logTotal;
        ctx.logfact = logfact;

        if (E == 0) {
            return evalPartition(cnt, ctx, n);
        }

        expectedArea = 0.0;
        rec(E, E, cnt, ctx);
        return expectedArea;
    }

    public static String solve() {
        double[] logfact = new double[101];
        for (int i = 1; i <= 100; i++) {
            double sum = 0.0;
            for (int k = 1; k <= i; k++)
                sum += Math.log(k);
            logfact[i] = sum;
        }

        double S = 0.0;
        for (int n = 3; n <= 50; n++) {
            S += EofN(n, logfact);
        }

        return String.format(java.util.Locale.US, "%.6f", S);
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
