import java.util.*;

public class Euler576 {
    static int[] primesUpTo(int n) {
        boolean[] np = new boolean[n + 1];
        np[0] = np[1] = true;
        for (int i = 2; (long) i * i <= n; i++)
            if (!np[i])
                for (int j = i * i; j <= n; j += i)
                    np[j] = true;
        int c = 0;
        for (int i = 2; i <= n; i++)
            if (!np[i])
                c++;
        int[] p = new int[c];
        c = 0;
        for (int i = 2; i <= n; i++)
            if (!np[i])
                p[c++] = i;
        return p;
    }

    static double[][] buildFirstHitSegments(double alpha, double g) {
        double domR = 1.0 - g;
        TreeMap<Double, Double> uncovered = new TreeMap<>();
        uncovered.put(0.0, domR);
        double remaining = domR;
        List<double[]> segs = new ArrayList<>();
        double x = 0;
        int k = 0;
        while (!uncovered.isEmpty() && remaining > 1e-15) {
            k++;
            x += alpha;
            x -= Math.floor(x);
            double L = Math.max(x - g, 0.0), U = Math.min(x, domR);
            if (L + 1e-18 >= U)
                continue;
            Map.Entry<Double, Double> entry = uncovered.floorEntry(L);
            if (entry == null)
                entry = uncovered.firstEntry();
            while (entry != null) {
                double a = entry.getKey(), b = entry.getValue();
                if (b <= L + 1e-18) {
                    entry = uncovered.higherEntry(a);
                    continue;
                }
                if (a >= U - 1e-18)
                    break;
                double ol = Math.max(a, L), orr = Math.min(b, U);
                if (ol + 1e-18 < orr) {
                    segs.add(new double[] { ol, orr, k });
                    remaining -= (orr - ol);
                }
                uncovered.remove(a);
                if (a + 1e-18 < L)
                    uncovered.put(a, Math.min(L, b));
                if (U + 1e-18 < b)
                    uncovered.put(Math.max(U, a), b);
                entry = uncovered.higherEntry(a);
            }
        }
        segs.sort(Comparator.comparingDouble(s -> s[0]));
        List<double[]> merged = new ArrayList<>();
        for (double[] s : segs) {
            if (merged.isEmpty()) {
                merged.add(s);
                continue;
            }
            double[] last = merged.get(merged.size() - 1);
            if ((int) s[2] == (int) last[2] && Math.abs(s[0] - last[1]) < 1e-15)
                last[1] = s[1];
            else
                merged.add(s);
        }
        return merged.toArray(new double[0][]);
    }

    public static void main(String[] args) {
        int n = 100;
        double g = 0.00002;
        int[] ps = primesUpTo(n);
        int m = ps.length;
        double[] weight = new double[m];
        for (int i = 0; i < m; i++)
            weight[i] = Math.sqrt(1.0 / ps[i]);
        double[] cur = new double[m];
        List<double[]> events = new ArrayList<>(); // [pos, idx, newVal]
        for (int i = 0; i < m; i++) {
            double[][] segs = buildFirstHitSegments(weight[i], g);
            cur[i] = weight[i] * segs[0][2];
            for (int j = 1; j < segs.length; j++)
                events.add(new double[] { segs[j][0], i, weight[i] * segs[j][2] });
        }
        events.sort(Comparator.comparingDouble(e -> e[0]));
        double sum = 0;
        for (double v : cur)
            sum += v;
        double best = sum;
        for (int idx = 0; idx < events.size();) {
            double pos = events.get(idx)[0];
            while (idx < events.size() && Math.abs(events.get(idx)[0] - pos) < 1e-18) {
                int i = (int) events.get(idx)[1];
                sum += events.get(idx)[2] - cur[i];
                cur[i] = events.get(idx)[2];
                idx++;
            }
            if (sum > best)
                best = sum;
        }
        System.out.printf("%.4f%n", best);
    }
}
