Problem: Ksusha is a vigorous mathematician. She is keen on absolutely incredible mathematical riddles. 

Today Ksusha came across a convex polygon of non-zero area. She is now wondering: if she chooses a pair of distinct points uniformly among all integer points (points with integer coordinates) inside or on the border of the polygon and then draws a square with two opposite vertices lying in the chosen points, what will the expectation of this square's area be?

A pair of distinct points is chosen uniformly among all pairs of distinct points, located inside or on the border of the polygon. Pairs of points p, q (p ≠ q) and q, p are considered the same.

Help Ksusha! Count the required expectation.

Input

The first line contains integer n (3 ≤ n ≤ 105) — the number of vertices of Ksusha's convex polygon. Next n lines contain the coordinates of the polygon vertices in clockwise or counterclockwise order. The i-th line contains integers xi, yi (|xi|, |yi| ≤ 106) — the coordinates of the vertex that goes i-th in that order.

Output

Print a single real number — the required expected area. 

The answer will be considered correct if its absolute and relative error doesn't exceed 10 - 6.

Examples

Input

3
0 0
5 5
5 0


Output

4.6666666667


Input

4
-1 3
4 5
6 2
3 -5


Output

8.1583333333


Input

3
17 136
859 937
16 641


Output

66811.3704155169

Solution (in JAVA):

Solution:
import java.io.*;
import java.math.*;
import java.util.*;

public class Solution {
    InputReader reader;
    PrintWriter writer;

    Solution() {
        reader = new InputReader();
        writer = new PrintWriter(System.out);
    }

    public static void main(String[] args) {
        new Solution().run();
    }

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

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

        Point flip() {
            return new Point(y, x);
        }

        public int compareTo(Point o) {
            if (x != o.x) {
                return x - o.x;
            }
            return y - o.y;
        }

        Point subtract(Point o) {
            return new Point(x - o.x, y - o.y);
        }
    }

    long det(Point a, Point b) {
        return (long)a.x * b.y - (long)a.y * b.x;
    }

    final static int OFFSET = 1; //(int)1e6;

    boolean isConvex(Point a, Point b, Point c) {
        return det(b.subtract(a), c.subtract(b)) >= 0;
    }

    Point[] getConvex(Point[] points) {
        ArrayList <Point> hull = new ArrayList <Point>();
        for (Point p : points) {
            while (hull.size() >= 2 && !isConvex(hull.get(hull.size() - 2), hull.get(hull.size() - 1), p)) {
                hull.remove(hull.size() - 1);
            }
            hull.add(p);
        }
        while (hull.size() >= 2 && hull.get(hull.size() - 1).x == hull.get(hull.size() - 2).x) {
            hull.remove(hull.size() - 1);
        }
        return hull.toArray(new Point[0]);
    }

    Point[] reverse(Point[] points) {
        int n = points.length;
        Point[] ret = new Point[n];
        for (int i = 0; i < n; ++ i) {
            ret[i] = points[n - 1 - i];
        }
        return ret;
    }

    double solve(Point[] points) {
        int n = points.length;
        Arrays.sort(points);
        Point[] down = getConvex(points);
        Point[] up = reverse(getConvex(reverse(points)));
        int xMin = down[0].x;
        int xMax = down[down.length - 1].x;
        long total = 0;
        double sum = 0.0;
        double squareSum = 0.0;
        for (int x = xMin, i = 0, j = 0; x <= xMax; ++ x) {
            while (i + 1 < down.length && down[i + 1].x < x) {
                i ++;
            }
            while (j + 1 < up.length && up[j + 1].x < x) {
                j ++;
            }
            int yMin = (int)Math.ceil((double)(x - down[i].x) / (down[i + 1].x - down[i].x) * (down[i + 1].y - down[i].y)) + down[i].y;
            int yMax = (int)Math.floor((double)(x - up[j].x) / (up[j + 1].x - up[j].x) * (up[j + 1].y - up[j].y)) + up[j].y;
            int count = yMax - yMin + 1;
            total += count;
            sum += (double)count * x;
            squareSum += (double)count * x * x;
        }
        return (total * squareSum - sum * sum) / ((double)total * (total - 1));
    }

    public void run() {
        try {
            int n = reader.nextInt();
            Point[] points = new Point[n];
            for (int i = 0; i < n; ++ i) {
                int x = reader.nextInt();
                int y = reader.nextInt();
                points[i] = new Point(x + OFFSET, y + OFFSET);
            }
            double answer = solve(points);
            for (int i = 0; i < n; ++ i) {
                points[i] = points[i].flip();
            }
            answer += solve(points);
            writer.println(String.format("%.8f", answer));
        } catch (IOException ex) {
        }
        writer.close();
    }
}

class InputReader {
    BufferedReader reader;
    StringTokenizer tokenizer;

    InputReader() {
        reader = new BufferedReader(new InputStreamReader(System.in));
        tokenizer = new StringTokenizer("");
    }

    String next() throws IOException {
        while (!tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    Integer nextInt() throws IOException {
        return Integer.parseInt(next());
    }
}