import java.util.*;
import java.util.stream.IntStream;

public class Euler353 {

    static class Point implements Comparable<Point> {
        int x, y, z;

        Point(int x, int y, int z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        @Override
        public int compareTo(Point o) {
            if (this.z != o.z)
                return Integer.compare(o.z, this.z);
            if (this.y != o.y)
                return Integer.compare(o.y, this.y);
            return Integer.compare(o.x, this.x);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (o == null || getClass() != o.getClass())
                return false;
            Point p = (Point) o;
            return x == p.x && y == p.y && z == p.z;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y, z);
        }
    }

    static double edgeRisk(Point a, Point b, int r) {
        double dot = (double) a.x * b.x + (double) a.y * b.y + (double) a.z * b.z;
        double c = dot / ((double) r * r);
        if (c > 1.0)
            c = 1.0;
        if (c < -1.0)
            c = -1.0;
        double t = Math.acos(c) / Math.PI;
        return t * t;
    }

    static class ReducedResult {
        List<Point> pts;
        double[] asinPi;
    }

    static ReducedResult generateReducedPoints(int r) {
        ReducedResult res = new ReducedResult();
        res.asinPi = new double[r + 1];
        double invR = 1.0 / r;
        for (int z = 0; z <= r; z++) {
            res.asinPi[z] = Math.asin((double) z * invR) / Math.PI;
        }

        Set<Point> set = new HashSet<>();
        long rr = (long) r * r;
        int z0 = r;

        for (int x = 0; 3L * x * x < rr; x++) {
            int y = x;
            int z = z0;
            long h = (long) x * x + (long) y * y + (long) z * z - rr;
            while (h > 0) {
                h -= 2L * z - 1L;
                z--;
            }
            z0 = z;
            while (y <= z) {
                if (h == 0) {
                    if (y == 0) {
                        set.add(new Point(0, 0, r));
                        set.add(new Point(0, r, 0));
                    } else if (x == 0) {
                        set.add(new Point(0, y, z));
                        set.add(new Point(0, z, y));
                        set.add(new Point(y, z, 0));
                    } else if (y == z) {
                        set.add(new Point(x, y, y));
                        set.add(new Point(y, y, x));
                    } else if (x == y) {
                        set.add(new Point(x, x, z));
                        set.add(new Point(x, z, x));
                    } else {
                        set.add(new Point(x, y, z));
                        set.add(new Point(x, z, y));
                        set.add(new Point(y, z, x));
                    }
                }
                h += 2L * y + 1L;
                y++;
                if (h > 0) {
                    h -= 2L * z - 1L;
                    z--;
                }
            }
        }
        res.pts = new ArrayList<>(set);
        Collections.sort(res.pts);
        return res;
    }

    static double dijkstraPruned(List<Point> pts, double[] asinPi, int r, double riskmax) {
        int n = pts.size();
        if (n < 2)
            return Double.POSITIVE_INFINITY;

        double[] risk = new double[n];
        boolean[] done = new boolean[n];
        Arrays.fill(risk, 2.0);

        int cur = 0;
        risk[0] = 0.0;

        while (true) {
            done[cur] = true;
            Point pc = pts.get(cur);
            double rc = risk[cur];

            if (riskmax > 0.0) {
                double dmax = riskmax - 2.0 * rc;
                for (int j = 0; j < n; j++) {
                    if (done[j])
                        continue;
                    Point pj = pts.get(j);
                    double f = asinPi[pc.z] - asinPi[pj.z];
                    if (f * f > dmax) {
                        if (j > cur)
                            break;
                        continue;
                    }
                    f = asinPi[pc.x] - asinPi[pj.x];
                    if (f * f > dmax)
                        continue;
                    f = asinPi[pc.y] - asinPi[pj.y];
                    if (f * f > dmax)
                        continue;

                    double nd = rc + edgeRisk(pc, pj, r);
                    if (nd < risk[j])
                        risk[j] = nd;
                }
            } else {
                for (int j = 0; j < n; j++) {
                    if (done[j] || j == cur)
                        continue;
                    double nd = rc + edgeRisk(pc, pts.get(j), r);
                    if (nd < risk[j])
                        risk[j] = nd;
                }
            }

            int next = -1;
            double best = 2.0;
            for (int j = 0; j < n; j++) {
                if (!done[j] && risk[j] < best) {
                    best = risk[j];
                    next = j;
                }
            }
            if (next < 0)
                break;
            cur = next;
        }

        double ans = 2.0;
        for (int i = 0; i < n; i++) {
            double e = 2.0 * asinPi[pts.get(i).z];
            double cand = 2.0 * risk[i] + e * e;
            if (cand < ans)
                ans = cand;
        }
        return ans;
    }

    static List<Point> downsample(List<Point> pts, int stride) {
        List<Point> out = new ArrayList<>();
        for (int i = 0; i < pts.size(); i += stride)
            out.add(pts.get(i));
        return out;
    }

    static double minimalRiskFast(int r) {
        ReducedResult res = generateReducedPoints(r);
        if (res.pts.size() < 2)
            return Double.POSITIVE_INFINITY;

        double d = 0.0;
        int[] strides = { 27, 9, 3, 1 };
        for (int stride : strides) {
            List<Point> sample = (stride == 1) ? res.pts : downsample(res.pts, stride);
            if (sample.size() < 2)
                continue;
            d = dijkstraPruned(sample, res.asinPi, r, d);
        }
        return d;
    }

    static double solve() {
        return IntStream.rangeClosed(1, 15).parallel()
                .mapToDouble(n -> minimalRiskFast((1 << n) - 1))
                .sum();
    }

    public static void main(String[] args) {
        System.out.printf(Locale.US, "%.10f\n", solve());
    }
}
