using System; using static System.Console; using System.Linq; using System.Collections.Generic; class Program { static int NN => int.Parse(ReadLine()); static int[] NList => ReadLine().Split().Select(int.Parse).ToArray(); static int[][] NArr(long n) => Enumerable.Repeat(0, (int)n).Select(_ => NList).ToArray(); public static void Main() { Solve(); } static void Solve() { var n = NN; var map = NArr(n); var p = 0L; var q = 0L; var r = (long)n * (n - 1) / 2; var s = r; var xset = new HashSet(); var yset = new HashSet(); var rdic = new Dictionary(); var sdic = new Dictionary(); foreach (var pt in map) { xset.Add(pt[0]); yset.Add(pt[1]); if (rdic.ContainsKey(pt[0])) ++rdic[pt[0]]; else rdic[pt[0]] = 1; if (sdic.ContainsKey(pt[1])) ++sdic[pt[1]]; else sdic[pt[1]] = 1; } foreach (var ri in rdic) r -= (long)ri.Value * (ri.Value - 1) / 2; foreach (var si in sdic) s -= (long)si.Value * (si.Value - 1) / 2; var xlist = new List(xset); xlist.Sort(); var ylist = new List(yset); ylist.Sort(); var xdic = new Dictionary(); for (var i = 0; i < xlist.Count; ++i) xdic[xlist[i]] = i; var ydic = new Dictionary(); for (var i = 0; i < ylist.Count; ++i) ydic[ylist[i]] = i; var plist = new List[ylist.Count]; for (var i = 0; i < plist.Length; ++i) plist[i] = new List(); for (var i = 0; i < n; ++i) { plist[ydic[map[i][1]]].Add(xdic[map[i][0]]); } var pft = new FenwickTree(xlist.Count); var mft = new FenwickTree(xlist.Count); for (var i = 0; i < plist.Length; ++i) { foreach (var x in plist[i]) pft.Add(x, 1); } for (var i = 0; i < plist.Length; ++i) { foreach (var x in plist[i]) pft.Add(x, -1); foreach (var x in plist[i]) { p += pft.Sum(xlist.Count - 1) - pft.Sum(x); if (x > 0) p += mft.Sum(x - 1); q += mft.Sum(xlist.Count - 1) - mft.Sum(x); if (x > 0) q += pft.Sum(x - 1); } } WriteLine((p - q) / Math.Sqrt(r) / Math.Sqrt(s)); } class FenwickTree { int size; long[] tree; public FenwickTree(int size) { this.size = size; tree = new long[size + 2]; } public void Add(int index, int value) { ++index; for (var x = index; x <= size; x += (x & -x)) tree[x] += value; } /// 先頭からindexまでの和(include index) public long Sum(int index) { if (index < 0) return 0; ++index; var sum = 0L; for (var x = index; x > 0; x -= (x & -x)) sum += tree[x]; return sum; } public long Get(int index) { if (index == 0) return Sum(0); return Sum(index) - Sum(index - 1); } /// Sum(x) >= value となる最小のxを求める // 各要素は非負であること public int LowerBound(long value) { if (value < 0) return -1; var x = 0; var b = 1; while (b * 2 <= size) b <<= 1; for (var k = b; k > 0; k >>= 1) { if (x + k <= size && tree[x + k] < value) { value -= tree[x + k]; x += k; } } return x; } } }