import java.util.*;
import java.io.*;

//Under construction.

public class guard_ab_overflow {
    public static void main(String[] arg) {
        new guard_ab_overflow().run();
    }

    StrictScanner in;
    PrintWriter out;

    public void run() {
        try {
            String problemName = this.getClass().getName().split("_")[0];
            in = new StrictScanner(new FileReader(problemName + ".in"));
            out = new PrintWriter(problemName + ".out");
            solve();
        } catch (Throwable e) {
            e.printStackTrace();
            System.exit(-1);
        } finally {
            out.close();
        }
    }

    final int MAXN = 100;
    final int MAX = 10000;

    void solve() throws Exception {
        int n = assertBetween(3, in.loadLine().nextInt(), MAXN, "n");
        long[][] p = new long[n][3];
        for (int i = 0; i < n; ++i) {
            p[i][0] = 1;
            p[i][1] = in.loadLine().nextInt();
            p[i][2] = in.skipSpace().nextInt();
        }

        long sq = 0;
        for (int i = 0; i < n; ++i) {
            long[] a = p[i];
            long[] b = p[(i + 1) % n];
            sq += vmul(a, b)[0];
            assert !isZero(vmul(a, b)) : "Equal points";
            assert smul(p[(i + 2) % n], vmul(a, b)) != 0 : "Three sequential points on a line";
            for (int j = 2; j < n - 1; ++j) {
                long[] c = p[(i + j) % n];
                long[] d = p[(i + j + 1) % n];
                assert !isZero(vmul(a, c)) : "Equal points";
                assert sign(smul(vmul(a, b), c)) == sign(smul(vmul(a, b), d)) || sign(smul(vmul(c, d), a)) == sign(smul(vmul(c, d), b)) : "Self-crossing";
            }
        }
        assert sq <= 0 : "Wrong orientation!";

        long[] sgn = new long[n];

        long[][] e = new long[n][];
        long[][] lsh = new long[n][];
        long[][] rsh = new long[n][];
        for (int i = 0; i < n; ++i) {
            int next = (i + 1) % n;
            e[i] = vmul(p[next], p[i]);
            lsh[i] = qmul(e[i], p[next]);
            rsh[i] = qmul(e[i], p[i]);
        }

        for (int i = 0; i < n; ++i) {
            loop:
            for (int j = 0; j < n; ++j) {
                if (i == j) continue;
                long[] line = vmul(p[j], p[i]);

                for (int k = 0; k < n; ++k) {
                    sgn[k] = sign(smul(p[k], line));
                }
                long[] ish = qmul(line, p[i]);
                assert cmp(ish, qmul(line, p[j])) < 0 : "Change the sign";
                long[] bf = new long[]{0, -1};
                int fi = -1;
                for (int k = 0; k < n; ++k) {
                    int next = (k + 1) % n;
                    long[] sh = null;
                    if (sgn[k] * sgn[next] < 0) {
                        sh = qmul(line, vmul(line, e[k]));
                    } else if (sgn[k] == 0) {
                        int prev = (k + n - 1) % n;
                        if (sgn[next] * sgn[prev] < 0) {
                            sh = qmul(line, p[k]);
                        } else {
                            long ux = p[k][1] - p[prev][1];
                            long uy = p[k][2] - p[prev][2];
                            long vx = p[next][1] - p[k][1];
                            long vy = p[next][2] - p[k][2];
                            if (ux * vy - uy * vx > 0) {
                                sh = qmul(line, p[k]);
                            } else {
                                continue;
                            }
                        }
                    }
                    if (sh != null) {
                        if (cmp(ish, sh) < 0) {
                            continue loop; //Not a ray up to infinity
                        } else if (cmp(sh, bf) > 0) {                            
                            bf = sh;
                            fi = k;
                        }
                    }
                }

                if (fi == -1) {
                    ish = new long[]{0, -1};
                }

                for (int k = 0; k < n; ++k) {
                    if (sgn[k] == 0) {
                        if (cmp(ish, qmul(line, p[k])) <= 0) {
                            lsh[k] = qmul(e[k], p[k]);
                            int prev = (k + n - 1) % n;
                            rsh[prev] = qmul(e[prev], p[k]);
                        }
                    }
                }
                if (fi != -1) {
                    long[] tsh = qmul(e[fi], vmul(line, e[fi]));
                    if (cmp(lsh[fi], tsh) > 0) {
                        lsh[fi] = tsh;
                    }
                    if (cmp(rsh[fi], tsh) < 0) {
                        rsh[fi] = tsh;
                    }
                }
            }
        }

        long[][] ans = new long[2 * n][];
        int m = 0;

        for (int i = 0; i < n; ++i) {
            if (cmp(lsh[i], rsh[i]) < 0) {
                long[] pl = getPoint(e[i], lsh[i]);
                if (m == 0 || !isZero(vmul(pl, ans[m - 1])) && !isZero(vmul(pl, ans[0]))) {
                    ans[m++] = pl;
                }
                long[] pr = getPoint(e[i], rsh[i]);
                if (m == 0 || !isZero(vmul(pr, ans[m - 1])) && !isZero(vmul(pr, ans[0]))) {
                    ans[m++] = pr;
                }
            }
        }

        out.println(m);
        for (int i = 0; i < m; ++i) {
            out.println(ans[i][1] * 1.0 / ans[i][0] + " " + ans[i][2] * 1.0 / ans[i][0]);
        }
    }

    public String toString(long[] p) {
        return p[1] * 1.0 / p[0] + " " + p[2] * 1.0 / p[0];
    }

    long[] getPoint(long[] line, long[] sh) {
        return vmul(new long[]{sh[1], sh[0] * line[2], - sh[0] * line[1]}, new long[]{line[0], line[1], line[2]});
    }

    long sign(long v) {
        return v > 0 ? 1 : v < 0 ? -1 : 0;
    }

    boolean isZero(long[] a) {
        return a[0] == 0 && a[1] == 0 && a[2] == 0;
    }

    long smul(long[] a, long[] b) {
        return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
    }

    long[] vmul(long[] a, long[] b) {
        return new long[]{
                a[1] * b[2] - a[2] * b[1],
                a[2] * b[0] - a[0] * b[2],
                a[0] * b[1] - a[1] * b[0]};
    }

    long[] qmul(long[] l, long[] p) {
        return new long[]{sign(p[0]) * p[0], sign(p[0]) * (l[1] * p[2] - l[2] * p[1])};
    }

    long cmp(long[] f1, long[] f2) {
        return sign(f1[1] * f2[0] - f2[1] * f1[0]);
    }

    int assertBetween(int l, int m, int r, String name) {
        assert l <= m && m <= r : "Variable " + name + " = " + m + " not in bounds [" + l + ", " + r + "]";
        return m;
    }

    class StrictScanner extends BufferedReader {

        private String cs;
        private int cpos;

        public StrictScanner(Reader a) {
            super(a);
        }

        boolean eoln() {
            return cpos == cs.length();
        }

        StrictScanner loadLine() throws IOException {
            assert cs == null || eoln();
            cs = readLine();
            cpos = 0;
            return this;
        }

        char nextChar() {
            return cs.charAt(cpos++);
        }

        String nextToken() {
            StringBuilder sb = new StringBuilder();
            while (cpos < cs.length() && cs.charAt(cpos) != ' ') {
                sb.append(cs.charAt(cpos));
                ++cpos;
            }
            return sb.toString();
        }

        int nextInt() {
            return Integer.parseInt(nextToken());
        }

        double nextDouble() {
            return Double.parseDouble(nextToken());
        }

        long nextLong() {
            return Long.parseLong(nextToken());
        }

        StrictScanner skipSpace() {
            char c = nextChar();
            assert c == ' ';
            return this;
        }
    }
}
