import java.util.*;

public class Euler829 {

    static class ShapeInfo {
        int left = -1;
        int right = -1;
        int leaves = 1;
    }

    static class HeapItem implements Comparable<HeapItem> {
        long prod;
        int i;
        int j;

        HeapItem(long prod, int i, int j) {
            this.prod = prod;
            this.i = i;
            this.j = j;
        }

        @Override
        public int compareTo(HeapItem o) {
            if (this.prod != o.prod)
                return Long.compare(this.prod, o.prod);
            if (this.i != o.i)
                return Integer.compare(this.i, o.i);
            return Integer.compare(this.j, o.j);
        }
    }

    static class Sequence {
        boolean needed = false;
        boolean leaf = false;
        boolean started = false;
        boolean exhausted = false;

        int left = -1;
        int right = -1;
        int nextI = 0;

        long nextPrime = 2;

        ArrayList<Long> values = new ArrayList<>();

        PriorityQueue<HeapItem> heap = new PriorityQueue<>();
        HashSet<Long> inHeap = new HashSet<>();
    }

    static Random rng = new Random(0);

    static ArrayList<ShapeInfo> shapes;
    static HashMap<Long, Integer> shapeIdByChildren;
    static HashMap<Long, Integer> shapeCache;
    static HashMap<Long, Long> bestDivisorCache;

    static HashMap<Long, Boolean> primeCache;
    static HashMap<Long, HashMap<Long, Integer>> factorCache;

    static long MAXVAL = 0;
    static Sequence[] seqs;

    static long mulMod(long a, long b, long mod) {
        long q = (long) ((double) a * b / mod);
        long r = a * b - q * mod;
        while (r < 0)
            r += mod;
        while (r >= mod)
            r -= mod;
        return r;
    }

    static long powMod(long a, long e, long mod) {
        long r = 1 % mod;
        a %= mod;
        while (e > 0) {
            if ((e & 1L) == 1L)
                r = mulMod(r, a, mod);
            a = mulMod(a, a, mod);
            e >>= 1L;
        }
        return r;
    }

    static boolean isPrime64(long n) {
        if (primeCache.containsKey(n))
            return primeCache.get(n);

        if (n < 2) {
            primeCache.put(n, false);
            return false;
        }
        long[] ps = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
        for (long p : ps) {
            if (n % p == 0) {
                primeCache.put(n, n == p);
                return n == p;
            }
        }

        long d = n - 1;
        int s = 0;
        while ((d & 1L) == 0) {
            d >>= 1L;
            s++;
        }

        long[] as = { 2, 325, 9375, 28178, 450775, 9780504, 1795265022 };
        for (long a : as) {
            if (a % n == 0)
                continue;
            long x = powMod(a, d, n);
            if (x == 1 || x == n - 1)
                continue;
            boolean comp = true;
            for (int r = 1; r < s; ++r) {
                x = mulMod(x, x, n);
                if (x == n - 1) {
                    comp = false;
                    break;
                }
            }
            if (comp) {
                primeCache.put(n, false);
                return false;
            }
        }

        primeCache.put(n, true);
        return true;
    }

    static long pollardRho(long n) {
        if ((n & 1L) == 0)
            return 2;
        if (n % 3 == 0)
            return 3;

        while (true) {
            long c = 2 + (long) (rng.nextDouble() * (n - 3));
            long x = 2 + (long) (rng.nextDouble() * (n - 3));
            long y = x;
            long d = 1;

            while (d == 1) {
                x = (mulMod(x, x, n) + c) % n;
                y = (mulMod(y, y, n) + c) % n;
                y = (mulMod(y, y, n) + c) % n;
                long diff = x > y ? x - y : y - x;
                d = gcd(diff, n);
            }

            if (d != n)
                return d;
        }
    }

    static long gcd(long a, long b) {
        while (b != 0) {
            long temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }

    static void factorRec(long n, HashMap<Long, Integer> fac) {
        if (n == 1)
            return;
        if (isPrime64(n)) {
            fac.put(n, fac.getOrDefault(n, 0) + 1);
            return;
        }
        long d = pollardRho(n);
        factorRec(d, fac);
        factorRec(n / d, fac);
    }

    static HashMap<Long, Integer> factorize(long n) {
        if (factorCache.containsKey(n))
            return factorCache.get(n);
        HashMap<Long, Integer> fac = new HashMap<>();
        factorRec(n, fac);
        factorCache.put(n, fac);
        return fac;
    }

    static class Pair {
        long p;
        int e;

        Pair(long p, int e) {
            this.p = p;
            this.e = e;
        }
    }

    static void genDivisorsRec(ArrayList<Pair> f, int idx, long cur, ArrayList<Long> out) {
        if (idx == f.size()) {
            out.add(cur);
            return;
        }
        Pair p = f.get(idx);
        long v = 1;
        for (int i = 0; i <= p.e; ++i) {
            genDivisorsRec(f, idx + 1, cur * v, out);
            v *= p.p;
        }
    }

    static long bestDivisorLeSqrt(long n) {
        if (bestDivisorCache.containsKey(n))
            return bestDivisorCache.get(n);

        HashMap<Long, Integer> facMap = factorize(n);
        ArrayList<Pair> f = new ArrayList<>();
        for (Map.Entry<Long, Integer> entry : facMap.entrySet()) {
            f.add(new Pair(entry.getKey(), entry.getValue()));
        }

        ArrayList<Long> divs = new ArrayList<>();
        genDivisorsRec(f, 0, 1, divs);

        long root = (long) Math.sqrt(n);
        while ((root + 1) * (root + 1) <= n)
            ++root;
        while (root * root > n)
            --root;

        long best = 1;
        for (long d : divs) {
            if (d <= root && d > best)
                best = d;
        }

        bestDivisorCache.put(n, best);
        return best;
    }

    static int makeShape(int l, int r) {
        long key = ((long) l << 32) | (r & 0xFFFFFFFFL);
        if (shapeIdByChildren.containsKey(key))
            return shapeIdByChildren.get(key);

        ShapeInfo s = new ShapeInfo();
        s.left = l;
        s.right = r;
        s.leaves = shapes.get(l).leaves + shapes.get(r).leaves;
        int id = shapes.size();
        shapes.add(s);
        shapeIdByChildren.put(key, id);
        return id;
    }

    static int shapeOf(long n) {
        if (shapeCache.containsKey(n))
            return shapeCache.get(n);
        if (isPrime64(n)) {
            shapeCache.put(n, 0);
            return 0;
        }

        long d = bestDivisorLeSqrt(n);
        long a = d;
        long b = n / d;
        if (a > b) {
            long temp = a;
            a = b;
            b = temp;
        }

        int l = shapeOf(a);
        int r = shapeOf(b);
        int id = makeShape(l, r);
        shapeCache.put(n, id);
        return id;
    }

    static Long getValueMaybe(int sh, int idx) {
        Sequence seq = seqs[sh];
        while (seq.values.size() <= idx) {
            Long nv = nextValue(sh);
            if (nv == null)
                return null;
            seq.values.add(nv);
        }
        return seq.values.get(idx);
    }

    static int ensureRightGe(int rightSh, long x) {
        Sequence rseq = seqs[rightSh];
        if (rseq.exhausted && (rseq.values.isEmpty() || rseq.values.get(rseq.values.size() - 1) < x))
            return -1;

        while (rseq.values.isEmpty() || rseq.values.get(rseq.values.size() - 1) < x) {
            Long nv = nextValue(rightSh);
            if (nv == null) {
                rseq.exhausted = true;
                break;
            }
            rseq.values.add(nv);
        }

        if (rseq.values.isEmpty() || rseq.values.get(rseq.values.size() - 1) < x)
            return -1;

        int low = 0;
        int high = rseq.values.size() - 1;
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (rseq.values.get(mid) < x) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return low;
    }

    static void pushPair(int sh, int i, int j) {
        Sequence seq = seqs[sh];
        long key = ((long) i << 32) | (j & 0xFFFFFFFFL);
        if (seq.inHeap.contains(key))
            return;

        Long x = getValueMaybe(seq.left, i);
        Long y = getValueMaybe(seq.right, j);
        if (x == null || y == null)
            return;
        if (x > y)
            return;

        if ((double) x * y > MAXVAL * 1.5) {
            // fast check to avoid exact 128 bit multiplication issue
            // wait, we can just use simple division
        }
        long maxDivX = MAXVAL / x;
        if (y > maxDivX)
            return;

        long prod = x * y;

        seq.inHeap.add(key);
        seq.heap.add(new HeapItem(prod, i, j));
    }

    static void startNode(int sh) {
        Sequence seq = seqs[sh];
        if (seq.started)
            return;
        seq.started = true;

        Long x0 = getValueMaybe(seq.left, 0);
        if (x0 == null) {
            seq.exhausted = true;
            return;
        }
        int j0 = ensureRightGe(seq.right, x0);
        if (j0 != -1) {
            pushPair(sh, 0, j0);
        }
        seq.nextI = 1;
    }

    static void maybeAddMoreI(int sh, long currentMin) {
        Sequence seq = seqs[sh];
        while (true) {
            Long x = getValueMaybe(seq.left, seq.nextI);
            if (x == null)
                return;

            long maxDivX = currentMin / x;
            if (!seq.heap.isEmpty() && x > maxDivX) {
                return;
            }

            int j0 = ensureRightGe(seq.right, x);
            if (j0 != -1) {
                pushPair(sh, seq.nextI, j0);
            }
            seq.nextI++;
        }
    }

    static Long nextCandidateProduct(int sh) {
        Sequence seq = seqs[sh];
        startNode(sh);
        if (seq.exhausted)
            return null;

        while (true) {
            if (seq.heap.isEmpty()) {
                Long x = getValueMaybe(seq.left, seq.nextI);
                if (x == null) {
                    seq.exhausted = true;
                    return null;
                }
                int j0 = ensureRightGe(seq.right, x);
                if (j0 == -1) {
                    seq.exhausted = true;
                    return null;
                }
                pushPair(sh, seq.nextI, j0);
                seq.nextI++;
                continue;
            }

            HeapItem cur = seq.heap.poll();
            long key = ((long) cur.i << 32) | (cur.j & 0xFFFFFFFFL);
            seq.inHeap.remove(key);

            maybeAddMoreI(sh, cur.prod);
            pushPair(sh, cur.i, cur.j + 1);

            return cur.prod;
        }
    }

    static Long nextValue(int sh) {
        Sequence seq = seqs[sh];
        if (seq.exhausted)
            return null;

        if (seq.leaf) {
            if (seq.nextPrime == 2) {
                seq.nextPrime = 3;
                return 2L;
            }
            for (long p = seq.nextPrime; p <= MAXVAL; p += 2) {
                if (isPrime64(p)) {
                    seq.nextPrime = p + 2;
                    return p;
                }
            }
            seq.exhausted = true;
            return null;
        }

        while (true) {
            Long cand = nextCandidateProduct(sh);
            if (cand == null) {
                seq.exhausted = true;
                return null;
            }
            if (!seq.values.isEmpty() && cand.equals(seq.values.get(seq.values.size() - 1))) {
                continue;
            }
            if (shapeOf(cand) == sh) {
                return cand;
            }
        }
    }

    static long getValue(int sh, int idx) {
        Long v = getValueMaybe(sh, idx);
        if (v == null) {
            throw new RuntimeException("sequence exhausted");
        }
        return v;
    }

    static long doubleFactorial(int n) {
        long r = 1;
        for (int k = n; k >= 2; k -= 2) {
            r *= k;
        }
        return r;
    }

    public static String solve() {
        shapes = new ArrayList<>();
        shapes.add(new ShapeInfo());
        shapeIdByChildren = new HashMap<>();
        shapeCache = new HashMap<>();
        bestDivisorCache = new HashMap<>();
        primeCache = new HashMap<>();
        factorCache = new HashMap<>();

        int maxN = 31;
        MAXVAL = doubleFactorial(maxN);

        int[] targets = new int[maxN - 1];
        for (int n = 2; n <= maxN; ++n) {
            targets[n - 2] = shapeOf(doubleFactorial(n));
        }

        boolean[] needed = new boolean[shapes.size()];
        class DFS {
            void collect(int sh) {
                if (needed[sh])
                    return;
                needed[sh] = true;
                if (sh == 0)
                    return;
                collect(shapes.get(sh).left);
                collect(shapes.get(sh).right);
            }
        }
        DFS dfs = new DFS();
        for (int sh : targets)
            dfs.collect(sh);

        seqs = new Sequence[shapes.size()];
        for (int i = 0; i < shapes.size(); i++)
            seqs[i] = new Sequence();

        for (int sh = 0; sh < shapes.size(); ++sh) {
            if (!needed[sh])
                continue;
            seqs[sh].needed = true;
            seqs[sh].leaf = (sh == 0);
            if (sh != 0) {
                seqs[sh].left = shapes.get(sh).left;
                seqs[sh].right = shapes.get(sh).right;
            }
        }

        long[] M = new long[maxN + 1];
        for (int n = 2; n <= maxN; ++n) {
            M[n] = getValue(targets[n - 2], 0);
        }

        long sum = 0;
        for (int n = 2; n <= maxN; ++n) {
            sum += M[n];
        }

        return Long.toString(sum);
    }

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