import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author aryssoncf
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        ECyclicCipher solver = new ECyclicCipher();
        solver.solve(1, in, out);
        out.close();
    }

    static class ECyclicCipher {
        static final int C = 5000;
        static double[][] pow2D = {{1, 0}};
        static int[][] rev2D = {};

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.readInt();
            int[] b = new int[n];
            int[] c = new int[n];

            for (int i = 0; i < n; i++) {
                b[i] = in.readInt();
            }

            int[] initB = b.clone();

            b = makeInvPows(b);

            for (int i = 0; i < n; i++) {
                c[i] = in.readInt();
            }

            int z, p;
            int[] pz;

            int[] fb;

            for (int i = 1; ; i++) {
                p = 2 * n * i + 1;
                if (p < C) {
                    continue;
                }
                if (!BigInteger.valueOf(p).isProbablePrime(30)) {
                    continue;
                }
                z = pow(primitiveRoot(p), (p - 1) / (2 * n), p);
                pz = new int[2 * n];
                pz[0] = 1;
                for (int j = 1; j < pz.length; j++) {
                    pz[j] = (int) ((long) pz[j - 1] * z % p);
                }

                fb = chirp(b, pz, p);
                boolean allGood = true;
                for (int coef : fb) {
                    allGood &= coef != 0;
                }

                if (allGood) {
                    break;
                }
            }

            int[] cc = new int[n];
            int inv2 = (p + 1) / 2;
            for (int i = 0; i < n; i++) {
                cc[i] = (c[(i + n - 1) % n] - c[i]) % p;
                if (cc[i] < 0) {
                    cc[i] += p;
                }
                cc[i] = (int) ((long) cc[i] * inv2 % p);
            }

            int[] fc = chirp(cc, pz, p);

            int[] fa = new int[n];
            for (int i = 0; i < n; i++) {
                fa[i] = (int) ((long) fc[i] * pow(fb[i], p - 2, p) % p);
            }

            int[] aa = chirp(fa, makeInvPows(pz), p);
            int invN = pow(n, p - 2, p);
            for (int i = 0; i < n; i++) {
                aa[i] = (int) ((long) aa[i] * invN % p);
            }

            long[] d = new long[n];
            for (int i = 1; i < n; i++) {
                d[i] = d[i - 1] + makeInt(aa[i], p);
            }

//		System.err.println(Arrays.toString(realAa));

            long B = 0;
            long C = -c[0];
            for (int i = 0; i < n; i++) {
                long diff = initB[i] - d[i];
                B -= diff;
                C += diff * diff;
            }

//		System.err.println(A + " " + B + " " + C);

            List<Long> x0s = new ArrayList<>();

            long D = B * B - (long) n * C;
            if (D >= 0) {
                if (D == 0) {
                    if ((-B % (long) n) == 0) {
                        x0s.add((-B) / (long) n);
                    }
                } else {
                    long rd = (long) Math.sqrt(D);
                    if (rd * rd == D) {
                        if ((-B - rd) % (long) n == 0) {
                            x0s.add((-B - rd) / (long) n);
                        }
                        if ((-B + rd) % (long) n == 0) {
                            x0s.add((-B + rd) / (long) n);
                        }
                    }
                }
            }

            out.printLine(x0s.size());
            for (long x0 : x0s) {
                for (int i = 0; i < n; i++) {
                    out.print(d[i] + x0 + " ");
                }
                out.printLine();
            }
        }

        int pow(int a, int b, int p) {
            int ret = 1;
            for (; b > 0; b >>= 1) {
                if ((b & 1) == 1) {
                    ret = (int) ((long) ret * a % p);
                }
                a = (int) ((long) a * a % p);
            }
            return ret;
        }

        int primitiveRoot(int p) {
            loop:
            for (int i = 2; ; i++) {
                for (int j = 2; j * j <= p - 1; j++) {
                    if ((p - 1) % j != 0) {
                        continue;
                    }
                    if (pow(i, (p - 1) / j, p) == 1) {
                        continue loop;
                    }
                    if (pow(i, j, p) == 1) {
                        continue loop;
                    }
                }
                return i;
            }
        }

        int[] chirp(int[] a, int[] pz, int p) {
            int n = a.length;
            // pz[1] has order 2 * n modulo prime p

            a = a.clone();
            for (int i = 0; i < n; i++) {
                a[i] %= p;
            }

            int[] one = new int[n];
            for (int i = 0; i < n; i++) {
                one[i] = (int) ((long) a[i] * pz[(int) ((long) i * i % (2 * n))] % p);
            }

            int[] two = new int[2 * n - 1];
            for (int i = 0; i <= 2 * n - 2; i++) {
                two[i] = pz[Math.floorMod(-(long) (n - 1 - i) * (n - 1 - i), 2 * n)];
            }

            int[] prod = mult(one, two, p);

            prod = Arrays.copyOfRange(prod, n - 1, 2 * n - 1);
            for (int i = 0; i < n; i++) {
                prod[i] = (int) ((long) prod[i] * pz[(int) ((long) i * i % (2 * n))] % p);
            }

            return prod;
            // returns polynomial a modulo p at points 1, rootZ^2, rootZ^4, ...
        }

        int makeInt(int x, int p) {
            return x < p / 2 ? x : x - p;
        }

        int[] makeInvPows(int[] a) {
            int[] b = new int[a.length];
            b[0] = a[0];
            for (int i = 1, j = a.length - 1; i < a.length; i++, j--) {
                b[i] = a[j];
            }
            return b;
        }

        static int nextPowerOf2(int x) {
            return x == 1 ? 1 : Integer.highestOneBit(x - 1) << 1;
        }

        static double[][] foo(int[] intV, int len, int L) {
            // pack into one complex vector
            double[] f = new double[len << 1];
            for (int i = 0; i < intV.length; i++) {
                f[i << 1] = intV[i] % L;
                f[i << 1 | 1] = intV[i] / L;
            }

            fft(f, false);

            // unpack
            double[] f1 = new double[len << 1];
            double[] f2 = new double[len << 1];

            // LEN MUST BE A POWER OF 2!!!
            int zzz = (len << 1) - 1;
            for (int i = 0; i < len << 1; i += 2) {
                int j = (-i) & zzz;
                f1[i] = .5 * (f[i] + f[j]);
                f1[i + 1] = .5 * (f[i + 1] - f[j + 1]);
                f2[i] = .5 * (f[i + 1] + f[j + 1]);
                f2[i + 1] = .5 * (f[j] - f[i]);
            }

            return new double[][]{f1, f2};
        }

        public static int[] mult(int[] a, int[] b, int pMod) {

            int k = (int) (Math.sqrt(pMod) + 1);
            int k2 = k * k % pMod;

            int len = nextPowerOf2(a.length + b.length - 1);
            int len2 = len << 1;

            double[][] fA = foo(a, len, k);
            double[][] fB = foo(b, len, k);

            double[][] invF = new double[2][len2];

            for (int ia = 0; ia < 2; ia++) {
                for (int ib = 0; ib < 2; ib++) {

                    double[] r = invF[(ia + ib) >> 1];
                    double[] p = fA[ia];
                    double[] q = fB[ib];

                    if (((ia + ib) & 1) == 0) {
                        for (int i = 0; i < len2; i += 2) {
                            r[i] += p[i] * q[i] - p[i + 1] * q[i + 1];
                            r[i + 1] += p[i] * q[i + 1] + p[i + 1] * q[i];
                        }

                    } else {
                        for (int i = 0; i < len2; i += 2) {
                            r[i] -= p[i] * q[i + 1] + p[i + 1] * q[i];
                            r[i + 1] += p[i] * q[i] - p[i + 1] * q[i + 1];
                        }
                    }

                }
            }

            fft(invF[0], true);
            fft(invF[1], true);

            int[] ret = new int[len];

            for (int i = 0; i < len2; i += 2) {
//			long v0 = Math.round(invF[0][i]) % P;
//			long v1 = Math.round(invF[0][i + 1]) % P * L % P;
//			long v2 = Math.round(invF[1][i]) % P * L2 % P;
                long v0 = (long) (invF[0][i] + .5);
                long v1 = ((long) (invF[0][i + 1] + .5)) % pMod * k;
                long v2 = ((long) (invF[1][i] + .5)) % pMod * k2;
                ret[i >> 1] = (int) ((v0 + v1 + v2) % pMod);
            }

            return ret;
        }

        public static void fft(double[] v, boolean invert) {
            int n2 = v.length;
            int n = n2 >> 1;
            int logN = Integer.numberOfTrailingZeros(n);
            prepareArrays(logN);
            int[] rev = rev2D[logN];

            for (int i = 0; i < n2; i += 2) {
                int j = rev[i >> 1] << 1;
                if (i < j) {
                    double t = v[i];
                    v[i] = v[j];
                    v[j] = t;
                    t = v[i + 1];
                    v[i + 1] = v[j + 1];
                    v[j + 1] = t;
                }
            }

            double conj = invert ? -1 : 1;

            for (int len = 2, row = 0; len <= n; len <<= 1, row++) {
                double[] pow = pow2D[row];
                for (int i = 0; i < n; i += len) {
                    for (int j1 = i << 1, j2 = j1 + len, k = 0; k < len; j1 += 2, j2 += 2, k += 2) {
                        double uA = v[j1];
                        double uB = v[j1 + 1];

                        double mRe = pow[k];
                        double mIm = pow[k + 1] * conj;

                        double vA = v[j2] * mRe - v[j2 + 1] * mIm;
                        double vB = v[j2] * mIm + v[j2 + 1] * mRe;

                        v[j1] = uA + vA;
                        v[j1 + 1] = uB + vB;
                        v[j2] = uA - vA;
                        v[j2 + 1] = uB - vB;
                    }
                }
            }
            if (invert) {
                for (int i = 0; i < n2; i++) {
                    v[i] /= n;
                }
            }
        }

        static void prepareArrays(int n) {
            if (rev2D.length < n + 1) {
                rev2D = Arrays.copyOf(rev2D, n + 1);
            }

            if (rev2D[n] == null) {
                int[] tmp = rev2D[n] = new int[1 << n];
                for (int i = 0; i < (1 << n); i++) {
                    tmp[i] = (tmp[i >> 1] >> 1) | ((i & 1) << (n - 1));
                }
            }

            int oldN = pow2D.length;

            if (oldN >= n) {
                return;
            }

            pow2D = Arrays.copyOf(pow2D, n);

            for (int i = oldN; i < n; i++) {
                double angle = Math.PI / (1 << i);

                double mRe = Math.cos(angle);
                double mIm = Math.sin(angle);

                double[] dst = pow2D[i] = new double[2 << i];
                double[] src = pow2D[i - 1];

                for (int j = 0; j < 1 << i; j += 2) {
                    double re = src[j];
                    double im = src[j + 1];

                    dst[j << 1] = re;
                    dst[j << 1 | 1] = im;
                    dst[j << 1 | 2] = re * mRe - im * mIm;
                    dst[j << 1 | 3] = re * mIm + im * mRe;
                }
            }
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void print(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
        }

        public void printLine() {
            writer.println();
        }

        public void close() {
            writer.close();
        }

        public void printLine(int i) {
            writer.println(i);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int readInt() {
            int c = read();
            while (isSpaceChar(c)) {
                c = read();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            boolean isSpaceChar(int ch);

        }

    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E {

	int pow(int a, int b, int p) {
		int ret = 1;
		for (; b > 0; b >>= 1) {
			if ((b & 1) == 1) {
				ret = (int) ((long) ret * a % p);
			}
			a = (int) ((long) a * a % p);
		}
		return ret;
	}

	int primitiveRoot(int p) {
		loop: for (int i = 2;; i++) {
			for (int j = 2; j * j <= p - 1; j++) {
				if ((p - 1) % j != 0) {
					continue;
				}
				if (pow(i, (p - 1) / j, p) == 1) {
					continue loop;
				}
				if (pow(i, j, p) == 1) {
					continue loop;
				}
			}
			return i;
		}
	}

	static final int C = 1000;

	int[] chirp(int[] a, int[] pz, int p) {
		int n = a.length;
		// pz[1] has order 2 * n modulo prime p

		a = a.clone();
		for (int i = 0; i < n; i++) {
			a[i] %= p;
		}

		int[] one = new int[n];
		for (int i = 0; i < n; i++) {
			one[i] = (int) ((long) a[i] * pz[i * i % (2 * n)] % p);
		}

		int[] two = new int[2 * n - 1];
		for (int i = 0; i <= 2 * n - 2; i++) {
			two[i] = pz[Math.floorMod(-(n - 1 - i) * (n - 1 - i), 2 * n)];
		}

		int[] prod = mult(one, two, p);

		prod = Arrays.copyOfRange(prod, n - 1, 2 * n - 1);
		for (int i = 0; i < n; i++) {
			prod[i] = (int) ((long) prod[i] * pz[i * i % (2 * n)] % p);
		}

		return prod;
		// returns polynomial a modulo p at points 1, rootZ^2, rootZ^4, ...
	}

	void submit() {
		int n = nextInt();
		int[] b = new int[n];
		int[] c = new int[n];

		for (int i = 0; i < n; i++) {
			b[i] = nextInt();
		}

		int[] initB = b.clone();

		b = makeInvPows(b);

		for (int i = 0; i < n; i++) {
			c[i] = nextInt();
		}

		int z, p;
		int[] pz;

		int[] fb;

		for (int i = 1;; i++) {
			p = 2 * n * i + 1;
			if (p < C) {
				continue;
			}
			if (!BigInteger.valueOf(p).isProbablePrime(30)) {
				continue;
			}
			z = pow(primitiveRoot(p), (p - 1) / (2 * n), p);
			pz = new int[2 * n];
			pz[0] = 1;
			for (int j = 1; j < pz.length; j++) {
				pz[j] = (int) ((long) pz[j - 1] * z % p);
			}

			fb = chirp(b, pz, p);
			boolean allGood = true;
			for (int coef : fb) {
				allGood &= coef != 0;
			}

			if (allGood) {
				break;
			}
		}

		int[] cc = new int[n];
		int inv2 = (p + 1) / 2;
		for (int i = 0; i < n; i++) {
			cc[i] = (c[(i + n - 1) % n] - c[i]) % p;
			if (cc[i] < 0) {
				cc[i] += p;
			}
			cc[i] = (int)((long)cc[i] * inv2 % p);
		}

		int[] fc = chirp(cc, pz, p);

		int[] fa = new int[n];
		for (int i = 0; i < n; i++) {
			fa[i] = (int)((long)fc[i] * pow(fb[i], p - 2, p) % p);
		}

		int[] aa = chirp(fa, makeInvPows(pz), p);
		int invN = pow(n, p - 2, p);
		for (int i = 0; i < n; i++) {
			aa[i] = (int)((long)aa[i] * invN % p);
		}

		long[] d = new long[n];
		for (int i = 1; i < n; i++) {
			d[i] = d[i - 1] + makeInt(aa[i], p);
		}

//		System.err.println(Arrays.toString(realAa));

		long A = n;
		long B = 0;
		long C = -c[0];
		for (int i = 0; i < n; i++) {
			long diff = initB[i] - d[i];
			B -= diff;
			C += diff * diff;
		}

//		System.err.println(A + " " + B + " " + C);

		List<Long> x0s = new ArrayList<>();

		long D = B * B - A * C;
		if (D < 0) {
		} else if (D == 0) {
			if ((-B % A) == 0) {
				x0s.add((-B) / A);
			}
		} else {
			long rd = (long) Math.sqrt(D);
			if (rd * rd == D) {
				if ((-B - rd) % A == 0) {
					x0s.add((-B - rd) / A);
				}
				if ((-B + rd) % A == 0) {
					x0s.add((-B + rd) / A);
				}
			}
		}

		out.println(x0s.size());
		for (long x0 : x0s) {
			for(int i = 0; i < n; i++) {
				out.print(d[i] + x0 + " ");
			}
			out.println();
		}

	}

	int makeInt(int x, int p) {
		return x < p / 2 ? x : x - p;
	}

	int[] makeInvPows(int[] a) {
		int[] b = new int[a.length];
		b[0] = a[0];
		for (int i = 1, j = a.length - 1; i < a.length; i++, j--) {
			b[i] = a[j];
		}
		return b;
	}

	void preCalc() {

	}

	void stress() {

	}

	void test() {

	}

	E() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		preCalc();
		submit();
		// stress();
		// test();
		out.close();
	}

	// this version is more precise
	// but looks like it might be a bit slower
	// I should profile and optimize it some day...

	static int nextPowerOf2(int x) {
		return x == 1 ? 1 : Integer.highestOneBit(x - 1) << 1;
	}

	static class CompV {
		double[] re, im;

		void add(CompV o) {
			for (int i = 0; i < re.length; i++) {
				re[i] += o.re[i];
				im[i] += o.im[i];
			}
		}

		static CompV times(CompV a, CompV b) {
			double[] aRe = a.re;
			double[] aIm = a.im;
			double[] bRe = b.re;
			double[] bIm = b.im;
			double[] re = new double[aRe.length];
			double[] im = new double[aRe.length];

			for (int i = 0; i < aRe.length; i++) {
				re[i] = aRe[i] * bRe[i] - aIm[i] * bIm[i];
				im[i] = aRe[i] * bIm[i] + aIm[i] * bRe[i];
			}

			return new CompV(re, im);
		}

		static CompV plus(CompV a, CompV b) {
			double[] aRe = a.re;
			double[] aIm = a.im;
			double[] bRe = b.re;
			double[] bIm = b.im;
			double[] re = new double[aRe.length];
			double[] im = new double[aRe.length];

			for (int i = 0; i < aRe.length; i++) {
				re[i] = aRe[i] + bRe[i];
				im[i] = aIm[i] + bIm[i];
			}

			return new CompV(re, im);
		}

		/**
		 * @return a + bi
		 */
		static CompV packFFT(CompV a, CompV b) {
			double[] aRe = a.re;
			double[] aIm = a.im;
			double[] bRe = b.re;
			double[] bIm = b.im;
			double[] re = new double[aRe.length];
			double[] im = new double[aRe.length];
			for (int i = 0; i < aRe.length; i++) {
				re[i] = aRe[i] - bIm[i];
				im[i] = aIm[i] + bRe[i];
			}
			return new CompV(re, im);
		}

		/**
		 * for real-valued a and b restores FFT(a) and FFT(b) from FFT(a + bi)
		 */
		void unpackFFT(CompV a, CompV b) {
			int n = re.length;
			double[] aRe = a.re;
			double[] aIm = a.im;
			double[] bRe = b.re;
			double[] bIm = b.im;
			for (int i = 0; i < n; i++) {
				int j = i == 0 ? 0 : n - i;
				aRe[i] = (re[i] + re[j]) * 0.5;
				aIm[i] = (im[i] - im[j]) * 0.5;
				bRe[i] = (im[i] + im[j]) * 0.5;
				bIm[i] = (re[j] - re[i]) * 0.5;
			}
		}

		public CompV(double[] re, double[] im) {
			this.re = re;
			this.im = im;
		}

		public CompV(int len) {
			re = new double[len];
			im = new double[len];
		}
	}

	// !!!!
	// TEST WITH JUST ONE MULTIPLICATION
	public static int[] mult(int[] a, int[] b, int p) {
		int len = nextPowerOf2(a.length + b.length - 1);

		int k = (int) (Math.sqrt(p) + 1);
		int k2 = k * k % p;

		double[] p1 = new double[len];
		double[] q1 = new double[len];
		for (int i = 0; i < a.length; i++) {
			p1[i] = a[i] % k;
			q1[i] = a[i] / k;
		}

		double[] p2 = new double[len];
		double[] q2 = new double[len];
		for (int i = 0; i < b.length; i++) {
			p2[i] = b[i] % k;
			q2[i] = b[i] / k;
		}

		CompV p1p2Pack = new CompV(p1, p2);
		CompV q1q2Pack = new CompV(q1, q2);

		fft(p1p2Pack, false);
		fft(q1q2Pack, false);

		CompV fp1 = new CompV(len);
		CompV fp2 = new CompV(len);
		p1p2Pack.unpackFFT(fp1, fp2);

		CompV fq1 = new CompV(len);
		CompV fq2 = new CompV(len);
		q1q2Pack.unpackFFT(fq1, fq2);

		CompV back0 = CompV.times(fp1, fp2);

		CompV back1 = CompV.times(fp1, fq2);
		back1.add(CompV.times(fq1, fp2));

		CompV back2 = CompV.times(fq1, fq2);

		CompV back01 = CompV.packFFT(back0, back1);

		fft(back01, true);
		fft(back2, true);

		int[] ret = new int[len];

		for (int i = 0; i < len; i++) {
			long v0 = Math.round(back01.re[i]) % p;
			long v1 = Math.round(back01.im[i]) % p * k % p;
			long v2 = Math.round(back2.re[i]) % p * k2 % p;
			ret[i] = (int) ((v0 + v1 + v2) % p);
		}

		return ret;
	}

	public static void fft(CompV v, boolean invert) {
		double[] a = v.re;
		double[] b = v.im;
		int n = a.length;
		int shift = 32 - Integer.numberOfTrailingZeros(n);
		prepareArrays(32 - shift);
		int[] rev = rev2D[32 - shift];
		// System.err.println(n + " " + shift);
		for (int i = 1; i < n; i++) {
			int j = rev[i];
			if (i < j) {
				double temp = a[i];
				a[i] = a[j];
				a[j] = temp;
				temp = b[i];
				b[i] = b[j];
				b[j] = temp;
			}
		}

		// this shit looks awkward
		double multInv = invert ? -1 : 1;

		for (int len = 2, row = 0; len <= n; len <<= 1, row++) {
			int halfLen = len >> 1;
			double[] multReArr = powRe[row];
			double[] multImArr = powIm[row];
			for (int i = 0; i < n; i += len) {
				int toJ = i + halfLen;

				for (int j1 = i, j2 = toJ, k = 0; k < halfLen; j1++, j2++, k++) {
					double uA = a[j1];
					double uB = b[j1];

					double multRe = multReArr[k];
					double multIm = multImArr[k] * multInv;

					double vA = a[j2] * multRe - b[j2] * multIm;
					double vB = a[j2] * multIm + b[j2] * multRe;
					a[j1] = uA + vA;
					b[j1] = uB + vB;
					a[j2] = uA - vA;
					b[j2] = uB - vB;
				}
			}
		}
		if (invert) {
			for (int i = 0; i < n; i++) {
				a[i] /= n;
				b[i] /= n;
			}
		}
	}

	static double[][] powRe = { { 1 } };
	static double[][] powIm = { { 0 } };
	static int[][] rev2D = {};

	static void prepareArrays(int n) {

		if (rev2D.length < n + 1) {
			rev2D = Arrays.copyOf(rev2D, n + 1);
		}

		if (rev2D[n] == null) {
			int[] tmp = rev2D[n] = new int[1 << n];
			for (int i = 0; i < (1 << n); i++) {
				tmp[i] = tmp[i >> 1] >> 1;
				if ((i & 1) == 1) {
					tmp[i] |= 1 << (n - 1);
				}
			}
		}

		int oldN = powRe.length;

		if (oldN >= n) {
			return;
		}

		powRe = Arrays.copyOf(powRe, n);
		powIm = Arrays.copyOf(powIm, n);

		for (int i = oldN; i < n; i++) {

			double angle = Math.PI / (1 << i);

			double multRe = Math.cos(angle);
			double multIm = Math.sin(angle);

			double[] toRe = powRe[i] = new double[1 << i];
			double[] toIm = powIm[i] = new double[1 << i];

			double[] fromRe = powRe[i - 1];
			double[] fromIm = powIm[i - 1];

			for (int j = 0; j < 1 << (i - 1); j++) {

				double re = fromRe[j];
				double im = fromIm[j];

				toRe[j << 1] = re;
				toIm[j << 1] = im;
				toRe[(j << 1) | 1] = re * multRe - im * multIm;
				toIm[(j << 1) | 1] = re * multIm + im * multRe;
			}

			// System.err.println(Arrays.toString(toRe));
			// System.err.println(Arrays.toString(toIm));
		}
	}

	static final Random rng = new Random();

	static int rand(int l, int r) {
		return l + rng.nextInt(r - l + 1);
	}

	public static void main(String[] args) throws IOException {
		new E();
	}

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

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

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

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


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

public class Main {
    static int inf = (int) 1e9 + 7;
    static int n, a[];

    static int min() {
        int ans = inf;
        for(int i = 0;i < n;i++) ans = Math.min(ans, a[i]);
        return ans;
    }

    static int cnt(int l, int r, int num) {
        int ans = 0;
        for(int i = l;i <= r;i++) if (a[i] == num) ans++;
        return ans;
    }

    static pair check(pair a) {
        if (a.l < 0 || a.r >= n) return new pair(0, 0, 0);
        return a;
    }

    static pair max(pair a, pair b) {
        a = check(a);
        b = check(b);
        if (a.ans > b.ans) return a;
        return b;
    }

    static void scan() throws IOException {
        n = sc.nextInt();
        char h[] = sc.next().toCharArray();
        a = new int [n];
        for(int i = 0;i < n;i++) {
            a[i] = (h[i] == '(' ? 1 : -1);
            if (i != 0) a[i] += a[i - 1];
        }
    }

    static pair zero() {
        return new pair(0, 0, cnt(0, n - 1, min()));
    }

    static pair plus() {
        int min = min();
        int l = inf;
        int r = -1;
        for(int i = 0;i < n;i++) {
            if (l == inf && a[i] == min) l = i;
            if (a[i] == min) r = i;
        }

        return max(plus1(l, r, min), plus2(l, r, min));
    }

    static pair plus1(int l, int r, int min) {
        int ans = cnt(0, l - 1, min + 1) + cnt(r + 1, n - 1, min + 1);
        return new pair(l, r + 1, ans);
    }

    static pair plus2(int l, int r, int min) {
        int l1 = l;
        int r1 = r;
        for(int i = 0;i < n;i++) {
            if (a[i] == min + 1 && l1 > i) l1 = i;
            if (a[i] == min + 1 && r1 < i) r1 = i;
        }

        int ans = cnt(0, n - 1, min);
        for(int i = 0;i < n;i++) {
            if ((i < l1 || i > r1) && a[i] == min + 2) ans++;
        }

        return new pair(l1, r1 + 1, ans);
    }

    static pair minus() {
        int min = min();
        int cnt = cnt(0, n - 1, min);
        int l = 0;
        pair ans = new pair(0, 0, 0);
        for(int i = 0;i < n;i++) {
            if (a[i] == min) {
                ans = max(ans, minus(l, i - 1, min, cnt));
                l = i + 1;
            }
        }
        return ans;
    }

    static pair minus(int l, int r, int min, int cnt) {
        int cnt1 = 0;
        int cnt2 = 0;
        pair ans = new pair(0, 0, 0);
        int l1 = l;
        for(int i = l;i <= r;i++) {
            if (a[i] == min + 1) {
                cnt1++;
                ans = max(ans, minus2(l1, i - 1, min, cnt));
                l1 = i + 1;
            }

            if (a[i] == min + 2) cnt2++;

        }

        ans = max(ans, minus2(l1, r, min, cnt));

        if (cnt1 > 0) return max(new pair(l, r + 1, cnt1), ans);
        return new pair(l, r + 1, cnt + cnt2);
    }

    static pair minus2(int l, int r, int min, int cnt) {
        return new pair(l, r + 1, cnt(l, r, min + 2) + cnt);
    }

    public static void main(String[] args) throws IOException {
        sc = new Scanner(System.in);
        pw = new PrintWriter(System.out);
        scan();
        if (a[n - 1] != 0) {
            System.out.println(0);
            System.out.println(1 + " " + 1);
            return;
        }
        pair ans = max(zero(), max(plus(), minus()));
        pw.println(ans.ans);
        pw.println(ans.l + 1 + " " + (ans.r + 1));

        pw.close();
    }

    static Scanner sc;
    static PrintWriter pw;

    static class Scanner {
        BufferedReader br;
        StringTokenizer st = new StringTokenizer("");

        Scanner(InputStream in) throws FileNotFoundException {
            br = new BufferedReader(new InputStreamReader(in));
        }

        Scanner(String in) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(in));
        }

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

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

        long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}

class pair {
    int l, r, ans;

    pair(int l, int r, int ans) {
        this.l = l;
        this.r = r;
        this.ans = ans;
    }

    pair() {}
}


import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Locale;
import java.util.Scanner;

public class TaskD {
    private static final String QUICK_ANSWER = "NO";
    private final Scanner in;
    private final StringBuilder out;
    private final int n;
    private final char[] chars;
    private final boolean[] up;
    int minPos;

    public TaskD(Scanner in, StringBuilder out) throws QuickAnswer {
        this.in = in;
        this.out = out;
        n = nextInt();
        chars = nextString().toCharArray();
        int lev = 0;
        int minLev = 0;
        int minPos = 0;
        for (int i = 0; i < n; i++) {
            if (chars[i] == '(') ++lev;
            else --lev;
            if (lev < minLev) {
                minLev = lev;
                minPos = i + 1;
            }
        }
        if (lev != 0) {
            quickAnswer("0\n1 1");
        }
        minPos %= n;
        this.minPos = minPos;
        up = new boolean[n];
        for (int i = 0; i < n; i++) {
            up[i] = chars[(i + minPos) % n] == '(';
        }
    }

    public void solve() throws QuickAnswer {
        int lev = 0;
        int i1 = 0;
        int i2 = 0;
        int bonus = 0;
        int istart = -1;
        int b = 1;
        int cnt0 = 0;
        int cnt1 = 0;
        for (int i = 0; i < n; i++) {
            if (up[i]) lev++;
            else lev--;
            if (lev == 0) ++cnt0;
            if (lev == 1) ++cnt1;
            if (lev == 2) {
                if (up[i]) istart = i;
                else ++b;
            } else if (lev == 1 && !up[i]) {
                if (b > bonus) {
                    i1 = istart;
                    i2 = i;
                    bonus = b;
                }
                istart = -1;
                b = 1;
            }
        }
        up[i1] = false;
        up[i2] = true;
        lev = 0;
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if (up[i]) lev++;
            else lev--;
            if (lev == 0) ++cnt;
        }
        if (cnt0 == 1 && cnt1 > cnt) {
            cnt = cnt1;
            i1 = 0;
            i2 = n - 1;
        }

        println(cnt);
        print(1 + (i1 + minPos) % n, 1 + (i2 + minPos) % n);

    }

    // Common functions

    void quickAnswer(String answer) throws QuickAnswer {
        throw new QuickAnswer(answer);
    }

    void quickAnswer() throws QuickAnswer {
        quickAnswer(QUICK_ANSWER);
    }

    static class QuickAnswer extends Exception {
        private String answer;

        public QuickAnswer(String answer) {
            this.answer = answer;
        }
    }

    void print(Object... args) {
        String prefix = "";
        for (Object arg : args) {
            out.append(prefix);
            out.append(arg);
            prefix = " ";
        }
    }

    void println(Object... args) {
        print(args);
        out.append("\n");
    }

    void printsp(Object... args) {
        print(args);
        out.append(" ");
    }

    int nextInt() {
        return in.nextInt();
    }

    long nextLong() {
        return in.nextLong();
    }

    String nextString() {
        String res = in.nextLine();
        return res.trim().isEmpty() ? in.nextLine() : res;
    }

    int[] nextInts(int count) {
        int[] res = new int[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextInt();
        }
        return res;
    }

    long[] nextLongs(int count) {
        long[] res = new long[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextInt();
        }
        return res;
    }

    public static void main(String[] args) {
        doMain(System.in, System.out);
    }

    static void doMain(InputStream inStream, PrintStream outStream) {
        Scanner in = new Scanner(new BufferedInputStream(inStream)).useLocale(Locale.ENGLISH);
        StringBuilder totalOut = new StringBuilder();
        int count = 1;
        //count = in.nextInt();
        while (count-- > 0) {
            try {
                StringBuilder out = new StringBuilder();
                new TaskD(in, out).solve();
                totalOut.append(out.toString());
            } catch (QuickAnswer e) {
                totalOut.append(e.answer);
            }
            if (count > 0) {
                totalOut.append("\n");
            }
        }
        outStream.print(totalOut.toString());
    }
}


/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class Main
{
    static MyScanner scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null, null, "BaZ", 1 << 27) {
            public void run() {
                try {
                    solve();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static int idx1, idx2;
    static char c[];
    static void solve() throws IOException
    {
        //initIo(true);
        initIo(false);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        c = ne().toCharArray();
        int bal[] = new int[n];
        int open = 0;
        for(int i=0;i<n;++i) {
            if(c[i] == '(') {
                bal[i]++;
                open++;
            }
            else {
                bal[i]--;
            }
            if(i-1>=0) {
                bal[i]+=bal[i-1];
            }
        }
        if(open != n - open) {
            pl("0\n1 1");
            System.exit(0);
        }
        int min = Integer.MAX_VALUE, at = -1;
        for(int i=0;i<n;++i) {
            if(bal[i]<min) {
                min = bal[i];
                at = i;
            }
        }
        //pa("bal", bal);
        int arr[] = new int[n];
        int ptr = 0;
        for(int i=at+1;i<n;++i) {
            arr[ptr++] = bal[i] - min;
        }
        for(int i=0;i<=at;++i) {
            arr[ptr++] = bal[i] - min;
        }
        //pa("arr", arr);
        int max = -1, ans_idx1 = -1, ans_idx2 = -1;
        int zero = calc(arr,0,n,false, (at+1 ==n ? 0 : at+1));
        if(zero>max) {
            max = zero;
            ans_idx1 = idx1;
            ans_idx2 = idx2;
        }
        int one = calc(arr,1,n,false, (at+1 ==n ? 0 : at+1));
        if(one>max) {
            max = one;
            ans_idx1 = idx1;
            ans_idx2 = idx2;
        }
        int two = calc(arr,2,n,true, (at+1 ==n ? 0 : at+1));
        if(two>max) {
            max = two;
            ans_idx1 = idx1;
            ans_idx2 = idx2;
        }
        pl(max);
        pl((1+getOriginalIndex(at+1 == n ? 0 : at+1, n, ans_idx1)) + " " + (1+getOriginalIndex(at+1 == n ? 0 : at+1, n, ans_idx2)));
        pw.flush();
        pw.close();
    }
    static int getOriginalIndex(int from_where, int n, int idx) {
        if(idx<=n-1-from_where) {
            return from_where + idx;
        }
        else {
            return idx - (n-from_where);
        }
    }
    static int calc(int arr[], int k, int n, boolean shouldAdd, int from_where) {
        int till[] = new int[n];
        int cum[] = new int[n];
        int pref[] = new int[n];
        int suff[] = new int[n];
        for(int i=n-1;i>=0;--i) {
            if(arr[i] == 0) {
                ++suff[i];
            }
            if(i+1<n) {
                suff[i]+=suff[i+1];
            }
        }
        for(int i=0;i<n;++i) {
            if(arr[i] == k) {
                cum[i]++;
            }
            if(arr[i] == 0) {
                ++pref[i];
            }
            if(i>0) {
                cum[i]+=cum[i-1];
                pref[i]+=pref[i-1];
            }
        }
        for(int i=n-1;i>=0;--i) {
            if(arr[i] >= k) {
                till[i] = (i+1 < n  ? till[i+1] : n);
            }
            else {
                till[i] = i;
            }
        }
        int max = -1;
        for(int i=0;i<n;++i) {
            if(till[i]==i) {
                continue;
            }
            if(c[getOriginalIndex(from_where, n, i)] == ')') {
                continue;
            }
            int ispe = (till[i] - 1 > 0 ? cum[till[i] - 1] : 0) - (i > 0 ? cum[i-1] : 0);
            if(shouldAdd) {
                ispe+=(i-1>0 ? pref[i-1] : 0);
                ispe+=(till[i] < n ? suff[till[i]] : 0);
            }
            if(max<ispe) {
                idx1 = i;
                idx2 = min(n-1, till[i]);
                max = ispe;
            }
        }
        return max;
    }
    static void initIo(boolean isFileIO) throws IOException {
        scan = new MyScanner(isFileIO);
        if(isFileIO) {
            pw = new PrintWriter("/Users/amandeep/Desktop/output.txt");
        }
        else {
            pw = new PrintWriter(System.out, true);
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static String ne() throws IOException
    {
        return scan.next();
    }
    static String nel() throws IOException
    {
        return scan.nextLine();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class MyScanner
    {
        BufferedReader br;
        StringTokenizer st;
        MyScanner(boolean readingFromFile) throws IOException
        {
            if(readingFromFile) {
                br = new BufferedReader(new FileReader("/Users/amandeep/Desktop/input.txt"));
            }
            else {
                br = new BufferedReader(new InputStreamReader(System.in));
            }
        }
        String nextLine()throws IOException
        {
            return br.readLine();
        }
        String next() throws IOException
        {
            if(st==null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }
        int nextInt() throws IOException
        {
            return Integer.parseInt(next());
        }
        long nextLong() throws IOException
        {
            return Long.parseLong(next());
        }
        double nextDouble() throws IOException
        {
            return Double.parseDouble(next());
        }
    }
}


/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class Main
{
    static MyScanner scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null, null, "BaZ", 1 << 27) {
            public void run() {
                try {
                    solve();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static int idx1, idx2;
    static void solve() throws IOException
    {
        //initIo(true);
        initIo(false);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        char c[] = ne().toCharArray();
        int bal[] = new int[n];
        int open = 0;
        for(int i=0;i<n;++i) {
            if(c[i] == '(') {
                bal[i]++;
                open++;
            }
            else {
                bal[i]--;
            }
            if(i-1>=0) {
                bal[i]+=bal[i-1];
            }
        }
        if(open != n - open) {
            pl("0\n1 1");
            System.exit(0);
        }
        int min = Integer.MAX_VALUE, at = -1;
        for(int i=0;i<n;++i) {
            if(bal[i]<min) {
                min = bal[i];
                at = i;
            }
        }
        //pa("bal", bal);
        int arr[] = new int[n];
        int ptr = 0;
        for(int i=at+1;i<n;++i) {
            arr[ptr++] = bal[i] - min;
        }
        for(int i=0;i<=at;++i) {
            arr[ptr++] = bal[i] - min;
        }
        //pa("arr", arr);
        int max = -1, ans_idx1 = -1, ans_idx2 = -1;
        int zero = calc(arr,0,n,false);
        if(zero>max) {
            max = zero;
            ans_idx1 = idx1;
            ans_idx2 = idx2;
        }
        int one = calc(arr,1,n,false);
        if(one>max) {
            max = one;
            ans_idx1 = idx1;
            ans_idx2 = idx2;
        }
        int two = calc(arr,2,n,true);
        if(two>max) {
            max = two;
            ans_idx1 = idx1;
            ans_idx2 = idx2;
        }
        pl(max);
        pl((1+getOriginalIndex(at+1 == n ? 0 : at+1, n, ans_idx1)) + " " + (1+getOriginalIndex(at+1 == n ? 0 : at+1, n, ans_idx2)));
        pw.flush();
        pw.close();
    }
    static int getOriginalIndex(int from_where, int n, int idx) {
        if(idx<=n-1-from_where) {
            return from_where + idx;
        }
        else {
            return idx - (n-from_where);
        }
    }
    static int calc(int arr[], int k, int n, boolean shouldAdd) {
        int till[] = new int[n];
        int cum[] = new int[n];
        int pref[] = new int[n];
        int suff[] = new int[n];
        for(int i=n-1;i>=0;--i) {
            if(arr[i] == 0) {
                ++suff[i];
            }
            if(i+1<n) {
                suff[i]+=suff[i+1];
            }
        }
        for(int i=0;i<n;++i) {
            if(arr[i] == k) {
                cum[i]++;
            }
            if(arr[i] == 0) {
                ++pref[i];
            }
            if(i>0) {
                cum[i]+=cum[i-1];
                pref[i]+=pref[i-1];
            }
        }
        for(int i=n-1;i>=0;--i) {
            if(arr[i] >= k) {
                till[i] = (i+1 < n  ? till[i+1] : n);
            }
            else {
                till[i] = i;
            }
        }
        int max = -1;
        for(int i=0;i<n;++i) {
            if(till[i]==i) {
                continue;
            }
            int ispe = (till[i] - 1 > 0 ? cum[till[i] - 1] : 0) - (i > 0 ? cum[i-1] : 0);
            if(shouldAdd) {
                ispe+=(i-1>0 ? pref[i-1] : 0);
                ispe+=(till[i] < n ? suff[till[i]] : 0);
            }
            if(max<ispe) {
                idx1 = i;
                idx2 = min(n-1, till[i]);
                max = ispe;
            }
        }
        return max;
    }
    static void initIo(boolean isFileIO) throws IOException {
        scan = new MyScanner(isFileIO);
        if(isFileIO) {
            pw = new PrintWriter("/Users/amandeep/Desktop/output.txt");
        }
        else {
            pw = new PrintWriter(System.out, true);
        }
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static String ne() throws IOException
    {
        return scan.next();
    }
    static String nel() throws IOException
    {
        return scan.nextLine();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class MyScanner
    {
        BufferedReader br;
        StringTokenizer st;
        MyScanner(boolean readingFromFile) throws IOException
        {
            if(readingFromFile) {
                br = new BufferedReader(new FileReader("/Users/amandeep/Desktop/input.txt"));
            }
            else {
                br = new BufferedReader(new InputStreamReader(System.in));
            }
        }
        String nextLine()throws IOException
        {
            return br.readLine();
        }
        String next() throws IOException
        {
            if(st==null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }
        int nextInt() throws IOException
        {
            return Integer.parseInt(next());
        }
        long nextLong() throws IOException
        {
            return Long.parseLong(next());
        }
        double nextDouble() throws IOException
        {
            return Double.parseDouble(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

public class Emperor implements Runnable {
    static class Side implements Comparable<Side> {
        int dx;
        int dy;
        double alpha;
        Side next;

        public int compareTo(Side side) {
            return Double.compare(alpha, side.alpha);
        }

        public void getAlpha() {
            alpha = Math.atan2(dy, dx);
        }
    }

    static final int MAX = 500;
    static final int MAGIC = 7;
    List<Side> res;
    int tdx;
    int tdy;

    private void solve() throws IOException {
        int n = nextInt();
        Side[] first = new Side[MAX * MAX + 1];
        for (int dx = -MAX; dx <= MAX; ++dx)
            for (int dy = -MAX; dy <= MAX; ++dy) {
                int z = dx * dx + dy * dy;
                if (z <= MAX * MAX) {
                    Side s = new Side();
                    s.dx = dx;
                    s.dy = dy;
                    s.next = first[z];
                    first[z] = s;
                }
            }
        int total = 0;
        List<Side> firsts = new ArrayList<Side>();
        for (int len = 1;; ++len) {
            if (first[len] == null)
                continue;
            ++total;
            firsts.add(first[len]);
            if (total < n)
                continue;
            if (doit(firsts, n)) {
                System.err.println(n + " " + total);
                break;
            }
        }
        for (Side s : res)
            s.getAlpha();
        Collections.sort(res);
        int x = 0;
        int y = 0;
        writer.println("YES");
        for (Side s : res) {
            writer.println(x + " " + y);
            x += s.dx;
            y += s.dy;
        }
    }

    private boolean doit(List<Side> firsts, int n) {
        res = new ArrayList<Side>();
        tdx = 0;
        tdy = 0;
        return rec(firsts, n, firsts.size() - 1);
    }

    private boolean rec(List<Side> firsts, int toMake, int at) {
        if (toMake == 0) {
            return (tdx == 0 && tdy == 0);
        }
        if (at < 0) {
            throw new RuntimeException();
        }
        if (at >= MAGIC) {
            Side best = firsts.get(at);
            int bdist = (tdx + best.dx) * (tdx + best.dx) + (tdy + best.dy) * (tdy + best.dy);
            Side cur = best.next;
            while (cur != null) {
                int cdist = (tdx + cur.dx) * (tdx + cur.dx) + (tdy + cur.dy) * (tdy + cur.dy);
                if (cdist < bdist) {
                    bdist = cdist;
                    best = cur;
                }
                cur = cur.next;
            }
            res.add(best);
            tdx += best.dx;
            tdy += best.dy;
            if (rec(firsts, toMake - 1, at - 1))
                return true;
            res.remove(res.size() - 1);
            tdx -= best.dx;
            tdy -= best.dy;
        } else {
            Side best = firsts.get(at);
            while (best != null) {
                res.add(best);
                tdx += best.dx;
                tdy += best.dy;
                if (rec(firsts, toMake - 1, at - 1))
                    return true;
                res.remove(res.size() - 1);
                tdx -= best.dx;
                tdy -= best.dy;
                best = best.next;
            }
            if (at >= toMake)
                if (rec(firsts, toMake, at - 1))
                    return true;
        }
        return false;
    }

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

    BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter writer;

    public void run() {
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            writer = new PrintWriter(System.out);
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

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

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

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


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

public class Solution {
    boolean[] isSq;
    int[] lens;
    int[] cnt;
    int[][] vx, vy;

    int N;

    int[] solX, solY;

    boolean[][][][] was;

    final int LIM = 90;

    class Segment implements Comparable<Segment> {
        int dx, dy;
        double angle;

        public Segment(int dx, int dy) {
            this.dx = dx;
            this.dy = dy;
            this.angle = Math.atan2(dy, dx);
        }

        public int compareTo(Segment other) {
            return new Double(this.angle).compareTo(new Double(other.angle));
        }
    }

    int it = 0;
    boolean retFlag = false;

    boolean[] skipped;

    void go(int pos, int take, int curX, int curY, int skip) {
        /*if (Math.abs(curX) >= LIM || Math.abs(curY) >= LIM)
            return;*/

        if (take == N) {
            if (curX==0 && curY==0) {
                System.out.println("YES");

                Segment[] segm = new Segment[N];
                for (int i=0; i < N; i++)
                    segm[i] = new Segment(solX[i], solY[i]);
                Arrays.sort(segm);
                int cx=0, cy=0;

                for (int i=0; i < N; i++) {
                    System.out.println(cx + " " + cy);
                    cx += segm[i].dx;
                    cy += segm[i].dy;
                }
                System.exit(0);
            }
            it++;
            if (it==10000) retFlag = true;
            return;
        }

        /*int A = Math.max(Math.abs(curX), Math.abs(curY));
        int B = Math.min(Math.abs(curX), Math.abs(curY));
        if (was[pos][A][B][skip]) {
            return;
        }
        was[pos][A][B][skip] = true;*/

        int[] nx = new int[cnt[pos]];
        int[] ny = new int[cnt[pos]];
        int[] dist = new int[cnt[pos]];

        for (int x=0; x < cnt[pos]; x++) {
            nx[x] = curX + vx[pos][x];
            ny[x] = curY + vy[pos][x];
            dist[x] = nx[x] * nx[x] + ny[x] * ny[x];
        }

        for (int x=0; x + 1 < cnt[pos]; x++)
            for (int y=0; y + 1 < cnt[pos]; y++)
                if (dist[y] > dist[y + 1]) {
                    int tmp = nx[y]; nx[y] = nx[y+1]; nx[y+1] = tmp;
                    tmp = ny[y]; ny[y] = ny[y+1]; ny[y+1] = tmp;
                    tmp = dist[y]; dist[y] = dist[y+1]; dist[y+1] = tmp;
                }

        if (skip > 0 && skipped[pos])
            go(pos - 1, take, curX, curY, skip - 1);

        if (retFlag) return;

        for (int x=0; x < cnt[pos]; x++) {
            solX[take] = nx[x] - curX;
            solY[take] = ny[x] - curY;
            go(pos - 1, take + 1, nx[x], ny[x], skip);
            if (retFlag) return;
        }
    }

    public void doMain() {
        Scanner sc = new Scanner(new InputStreamReader(System.in));
        N = sc.nextInt();

        if (N==3) {
            System.out.println("YES");
            System.out.println("0 0");
            System.out.println("1 0");
            System.out.println("0 2");
            System.exit(0);
        }

        isSq = new boolean[100000];
        for (int i=0; i*i < isSq.length; i++)
            isSq[i*i] = true;

        lens = new int[11000];
        vx = new int[11000][100];
        vy = new int[11000][100];
        cnt = new int[11000];

        int pos = 0;
        skipped = new boolean[N + 2];
        for (int len=1; ; len++) {
            boolean ok = false;
            for (int x=0; x*x <= len; x++) {
                if (!isSq[len-x*x]) continue;
                lens[pos] = len;
                int y = (int)Math.sqrt(len - x*x);
                ok = true;

                vx[pos][cnt[pos]] = x;
                vy[pos][cnt[pos]++] = y;

                if (x != 0) {
                    vx[pos][cnt[pos]] = -x;
                    vy[pos][cnt[pos]++] = y;
                }

                if (y != 0) {
                    vx[pos][cnt[pos]] = x;
                    vy[pos][cnt[pos]++] = -y;
                }

                if (x != 0 && y != 0) {
                    vx[pos][cnt[pos]] = -x;
                    vy[pos][cnt[pos]++] = -y;
                }
            }
            if (ok) {
                pos++;
            }
            if (pos == N + 1) break;
        }

        int oo = 0, ee = 0, oe = 0;
        for (int i=0; i < N; i++) {
            if (vx[i][0] % 2 == 0 && vy[i][0] % 2 == 0)
                ee++;
            else if (vx[i][0] % 2 == 1 && vy[i][0] % 2 == 1)
                oo++;
            else
                oe++;
        }

        int stSkip = 0;

        if (oe % 2 == 1) {
            stSkip = 1;
        }

        solX = new int[N];
        solY = new int[N];

        /*was = new boolean[N+2][LIM][][];

        for (int i=0; i < was.length; i++)
            for (int A=0; A<LIM; A++)
                was[i][A] = new boolean[A+1][2];*/

        for (int skip=stSkip; skip<2; skip = (skip + 1) % 2) {
            /*for (int i=0; i < was.length; i++)
                for (int j=0; j < was[i].length; j++)
                    for (int k=0; k < was[i][j].length; k++)
                        Arrays.fill(was[i][j][k], false);*/

            if (skip == 1) {
                for (int i=0; i < N+1; i++) {
                    skipped[i] = true;
                    retFlag = false;
                    it = 0;
                    go(N + skip - 1, 0, 0, 0, skip);
                    skipped[i] = false;
                }
            } else {
                retFlag = false;
                it = 0;
                go(N + skip - 1, 0, 0, 0, skip);
            }
        }
    }

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


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

public class Solution {
    boolean[] isSq;
    int[] lens;
    int[] cnt;
    int[][] vx, vy;

    int N;

    int[] solX, solY;

    boolean[][][][] was;

    final int LIM = 90;

    class Segment implements Comparable<Segment> {
        int dx, dy;
        double angle;

        public Segment(int dx, int dy) {
            this.dx = dx;
            this.dy = dy;
            this.angle = Math.atan2(dy, dx);
        }

        public int compareTo(Segment other) {
            return new Double(this.angle).compareTo(new Double(other.angle));
        }
    }

    int it = 0;
    boolean retFlag = false;

    boolean[] skipped;

    void go(int pos, int take, int curX, int curY, int skip) {
        /*if (Math.abs(curX) >= LIM || Math.abs(curY) >= LIM)
            return;*/

        if (take == N) {
            if (curX==0 && curY==0) {
                System.out.println("YES");

                Segment[] segm = new Segment[N];
                for (int i=0; i < N; i++)
                    segm[i] = new Segment(solX[i], solY[i]);
                Arrays.sort(segm);
                int cx=0, cy=0;

                for (int i=0; i < N; i++) {
                    System.out.println(cx + " " + cy);
                    cx += segm[i].dx;
                    cy += segm[i].dy;
                }
                System.exit(0);
            }
            it++;
            if (it==10000) retFlag = true;
            return;
        }

        /*int A = Math.max(Math.abs(curX), Math.abs(curY));
        int B = Math.min(Math.abs(curX), Math.abs(curY));
        if (was[pos][A][B][skip]) {
            return;
        }
        was[pos][A][B][skip] = true;*/

        int[] nx = new int[cnt[pos]];
        int[] ny = new int[cnt[pos]];
        int[] dist = new int[cnt[pos]];

        for (int x=0; x < cnt[pos]; x++) {
            nx[x] = curX + vx[pos][x];
            ny[x] = curY + vy[pos][x];
            dist[x] = nx[x] * nx[x] + ny[x] * ny[x];
        }

        for (int x=0; x + 1 < cnt[pos]; x++)
            for (int y=0; y + 1 < cnt[pos]; y++)
                if (dist[y] > dist[y + 1]) {
                    int tmp = nx[y]; nx[y] = nx[y+1]; nx[y+1] = tmp;
                    tmp = ny[y]; ny[y] = ny[y+1]; ny[y+1] = tmp;
                    tmp = dist[y]; dist[y] = dist[y+1]; dist[y+1] = tmp;
                }

        if (skip > 0 && skipped[pos])
            go(pos - 1, take, curX, curY, skip - 1);

        if (retFlag) return;

        for (int x=0; x < cnt[pos]; x++) {
            solX[take] = nx[x] - curX;
            solY[take] = ny[x] - curY;
            go(pos - 1, take + 1, nx[x], ny[x], skip);
            if (retFlag) return;
        }
    }

    public void doMain() {
        Scanner sc = new Scanner(new InputStreamReader(System.in));
        N = sc.nextInt();

        if (N==3) {
            System.out.println("YES");
            System.out.println("0 0");
            System.out.println("1 0");
            System.out.println("0 2");
            System.exit(0);
        }

        isSq = new boolean[100000];
        for (int i=0; i*i < isSq.length; i++)
            isSq[i*i] = true;

        lens = new int[11000];
        vx = new int[11000][100];
        vy = new int[11000][100];
        cnt = new int[11000];

        int pos = 0;
        skipped = new boolean[N + 2];
        for (int len=1; ; len++) {
            boolean ok = false;
            for (int x=0; x*x <= len; x++) {
                if (!isSq[len-x*x]) continue;
                lens[pos] = len;
                int y = (int)Math.sqrt(len - x*x);
                ok = true;

                vx[pos][cnt[pos]] = x;
                vy[pos][cnt[pos]++] = y;

                if (x != 0) {
                    vx[pos][cnt[pos]] = -x;
                    vy[pos][cnt[pos]++] = y;
                }

                if (y != 0) {
                    vx[pos][cnt[pos]] = x;
                    vy[pos][cnt[pos]++] = -y;
                }

                if (x != 0 && y != 0) {
                    vx[pos][cnt[pos]] = -x;
                    vy[pos][cnt[pos]++] = -y;
                }
            }
            if (ok) {
                pos++;
            }
            if (pos == N + 1) break;
        }

        int oo = 0, ee = 0, oe = 0;
        for (int i=0; i < N; i++) {
            if (vx[i][0] % 2 == 0 && vy[i][0] % 2 == 0)
                ee++;
            else if (vx[i][0] % 2 == 1 && vy[i][0] % 2 == 1)
                oo++;
            else
                oe++;
        }

        int stSkip = 0;

        if (oe % 2 == 1) {
            stSkip = 1;
        }

        solX = new int[N];
        solY = new int[N];

        /*was = new boolean[N+2][LIM][][];

        for (int i=0; i < was.length; i++)
            for (int A=0; A<LIM; A++)
                was[i][A] = new boolean[A+1][2];*/

        for (int skip=stSkip; skip<2; skip = (skip + 1) % 2) {
            /*for (int i=0; i < was.length; i++)
                for (int j=0; j < was[i].length; j++)
                    for (int k=0; k < was[i][j].length; k++)
                        Arrays.fill(was[i][j][k], false);*/

            if (skip > 1) {
                for (int i=0; i < N+1; i++) {
                    skipped[i] = true;
                    retFlag = false;
                    it = 0;
                    go(N + skip - 1, 0, 0, 0, skip);
                    skipped[i] = false;
                }
            } else {
                retFlag = false;
                it = 0;
                go(N + skip - 1, 0, 0, 0, skip);
            }
        }
    }

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


import java.math.*;
import java.util.*;

public class E {

	public Object solve () {
		int N = sc.nextInt() - 1, S = sc.nextInt(), R = sc.nextInt();

		if (N == 0)
			return exit(1);
		if (S == 0)
			return exit(modInv(N+1));

		C = modBin(N, N);
		long [] V = modInvs(N+1);

		long P = 0;
		for (int B = R; B <= S; ++B) {
			if (B * (N+1) < S)
				continue;
			for (int j = 0; j <= N; ++j) {
				int T = S - B * (j+1);
				if (T >= 0) {
					long D = F(B, N-j, T);
					if (T > 0)
						D = (D + MOD - F(B, N-j, T-1)) % MOD;
					long Z = (C[N][j] * D) % MOD;
					P = (P + Z * V[j+1]) % MOD;
				}
			}
		}

		long Q = F(S-R+1, N, S-R);

		long res = (P * modInv(Q)) % MOD;
		return exit(res);
	}

	long [][] C;

	int F(int B, int K, int X) {
		if (B == 0) return K == 0 ? 1 : 0;

		long Q = 6000L * (6000 * B + X) + K;
		Integer R = H.get(Q);
		if (R != null)
			return R;

		long res = 0;
		for (int j = 0; j <= K && j * (B-1) <= X; ++j)
			res = (res + C[K][j] * F(B-1, K-j, X - j * (B-1))) % MOD;
		H.put(Q, (int)res);
		return (int)res;
	}

	Map<Long, Integer> H = new HashMap<>();

	private static final boolean ONE_TEST_CASE = true;

	private static void init () {
	}

	private static final int MOD = 998244353;
	private static long mod (long x) { return mod(x, MOD); }
	private static long mod (long x, long mod) { return ((x % mod) + mod) % mod; }
	private static long [][] modBin (int N, int K) {
		long [][] res = new long [N+1][K+1];
		for (int n = 0; n <= N; ++n) {
			res[n][0] = 1;
			for (int k = 1; k <= K && k <= n; ++k)
				res[n][k] = mod(res[n-1][k] + res[n-1][k-1]);
		}
		return res;
	}
	private static long modInv(long x) { return modInv(x, MOD); }
	private static long modInv(long x, int mod) { return BigInteger.valueOf(x).modInverse(BigInteger.valueOf(mod)).longValue(); }
	private static long [] modInvs(int N) {
		long [] res = new long [N+1];
		for (int i = 1; i <= N; ++i)
			res[i] = modInv(i);
		return res;
	}
	//////////////////////////////////////////////////////////////////////////////////// OFF
	private static IOUtils.MyScanner sc = new IOUtils.MyScanner();
	private static Object print (Object o, Object ... A) { IOUtils.print(o, A); return null; }
	private static Object exit (Object o, Object ... A) { print(o, A); IOUtils.exit(); return null; }
	private static class IOUtils {
		public static class MyScanner {
			public String next () { newLine(); return line[index++]; }
			public int nextInt () { return Integer.parseInt(next()); }
			//////////////////////////////////////////////
			private boolean eol () { return index == line.length; }
			private String readLine () {
				try {
					return r.readLine();
				} catch (Exception e) {
					throw new Error (e);
				}
			}
			private final java.io.BufferedReader r;
			private MyScanner () { this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in))); }
			private MyScanner (java.io.BufferedReader r) {
				try {
					this.r = r;
					while (!r.ready())
						Thread.sleep(1);
					start();
				} catch (Exception e) {
					throw new Error(e);
				}
			}
			private String [] line;
			private int index;
			private void newLine () {
				if (line == null || eol()) {
					line = split(readLine());
					index = 0;
				}
			}
			private String [] split (String s) { return s.length() > 0 ? s.split(" ") : new String [0]; }
		}
		private static String build (Object o, Object ... A) { return buildDelim(" ", o, A); }
		private static String buildDelim (String delim, Object o, Object ... A) {
			StringBuilder b = new StringBuilder();
			append(b, o, delim);
			for (Object p : A)
				append(b, p, delim);
			return b.substring(delim.length());
		}
		//////////////////////////////////////////////////////////////////////////////////
		private static final java.text.DecimalFormat formatter = new java.text.DecimalFormat("#.#########");
		private static void start () { if (t == 0) t = millis(); }
		private static void append (java.util.function.Consumer<Object> f, java.util.function.Consumer<Object> g, final Object o) {
			if (o.getClass().isArray()) {
				int len = java.lang.reflect.Array.getLength(o);
				for (int i = 0; i < len; ++i)
					f.accept(java.lang.reflect.Array.get(o, i));
			}
			else if (o instanceof Iterable<?>)
				((Iterable<?>)o).forEach(f::accept);
			else
				g.accept(o instanceof Double ? formatter.format(o) : o);
		}
		private static void append (final StringBuilder b, Object o, final String delim) {
			append(x -> { append(b, x, delim); }, x -> b.append(delim).append(x), o);
		}
		private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out);
		private static void print (Object o, Object ... A) {
			pw.println(build(o, A));
			if (DEBUG)
				pw.flush();
		}
		private static void err (Object o, Object ... A) { System.err.println(build(o, A)); }
		private static boolean DEBUG;
		private static void write (Object o) {
			err(o, '(', time(), ')');
			if (!DEBUG)
				pw.println(o);
		}
		private static void exit () {
			IOUtils.pw.close();
			System.out.flush();
			err("------------------");
			err(time());
			System.exit(0);
		}
		private static long t;
		private static long millis () { return System.currentTimeMillis(); }
		private static String time () { return "Time: " + (millis() - t) / 1000.0; }
		private static void run (int N) {
			try { DEBUG = System.getProperties().containsKey("DEBUG"); }
			catch (Throwable t) {}

			for (int n = 1; n <= N; ++n) {
				Object res = new E().solve();
				if (res != null)
					write("Case #" + n + ": " + build(res));
			}
			exit();
		}
	}
	////////////////////////////////////////////////////////////////////////////////////
	public static void main (String[] args) {
		init();
		int N = ONE_TEST_CASE ? 1 : sc.nextInt();
		IOUtils.run(N);
	}
}


import static java.util.Arrays.*;

import java.math.*;

public class E {

	public Object solve () {
		int N = sc.nextInt() - 1, S = sc.nextInt(), R = sc.nextInt();

		if (N == 0)
			return exit(1);
		if (S == 0)
			return exit(modInv(N+1));

		long [][] C = modBin(N, N);

		long P = 0;
		for (int b = S; b >= R; --b) {
			if (b * N < S - b)
				break;

			long [][] F = new long [N+1][S+1]; fill(F[0], 1);
			for (int k = 1; k <= N; ++k) {
				F[k][0] = 1;
				for (int x = 1; x <= S; ++x) {
					F[k][x] = (F[k][x-1] + F[k-1][x]) % MOD;
					if (x >= b)
						F[k][x] = (F[k][x] + MOD - F[k-1][x-b]) % MOD;
				}
			}

			for (int j = 0; j <= N; ++j) {
				int T = S - b * (j+1);
				if (T >= 0) {
					long D = F[N-j][T];
					if (T > 0)
						D = (D + MOD - F[N-j][T-1]) % MOD;
					long Z = (C[N][j] * D) % MOD;
					P = (P + Z * modInv(j+1)) % MOD;
				}
			}
		}

		long Q = 0;
		long [][] F = new long [N+1][S+1]; fill(F[0], 1);
		for (int k = 1; k <= N; ++k) {
			F[k][0] = 1;
			for (int x = 1; x <= S; ++x)
				F[k][x] = (F[k][x-1] + F[k-1][x]) % MOD;
		}
		Q = F[N][S-R];

		long res = (P * modInv(Q)) % MOD;
		return exit(res);
	}

	private static final boolean ONE_TEST_CASE = true;

	private static void init () {
	}

	private static final int MOD = 998244353;
	private static long mod (long x) { return mod(x, MOD); }
	private static long mod (long x, long mod) { return ((x % mod) + mod) % mod; }
	private static long [][] modBin (int N, int K) {
		long [][] res = new long [N+1][K+1];
		for (int n = 0; n <= N; ++n) {
			res[n][0] = 1;
			for (int k = 1; k <= K && k <= n; ++k)
				res[n][k] = mod(res[n-1][k] + res[n-1][k-1]);
		}
		return res;
	}
	private static long modInv(long x) { return modInv(x, MOD); }
	private static long modInv(long x, int mod) { return BigInteger.valueOf(x).modInverse(BigInteger.valueOf(mod)).longValue(); }
	//////////////////////////////////////////////////////////////////////////////////// OFF
	private static IOUtils.MyScanner sc = new IOUtils.MyScanner();
	private static Object print (Object o, Object ... A) { IOUtils.print(o, A); return null; }
	private static Object exit (Object o, Object ... A) { print(o, A); IOUtils.exit(); return null; }
	private static class IOUtils {
		public static class MyScanner {
			public String next () { newLine(); return line[index++]; }
			public int nextInt () { return Integer.parseInt(next()); }
			//////////////////////////////////////////////
			private boolean eol () { return index == line.length; }
			private String readLine () {
				try {
					return r.readLine();
				} catch (Exception e) {
					throw new Error (e);
				}
			}
			private final java.io.BufferedReader r;
			private MyScanner () { this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in))); }
			private MyScanner (java.io.BufferedReader r) {
				try {
					this.r = r;
					while (!r.ready())
						Thread.sleep(1);
					start();
				} catch (Exception e) {
					throw new Error(e);
				}
			}
			private String [] line;
			private int index;
			private void newLine () {
				if (line == null || eol()) {
					line = split(readLine());
					index = 0;
				}
			}
			private String [] split (String s) { return s.length() > 0 ? s.split(" ") : new String [0]; }
		}
		private static String build (Object o, Object ... A) { return buildDelim(" ", o, A); }
		private static String buildDelim (String delim, Object o, Object ... A) {
			StringBuilder b = new StringBuilder();
			append(b, o, delim);
			for (Object p : A)
				append(b, p, delim);
			return b.substring(delim.length());
		}
		//////////////////////////////////////////////////////////////////////////////////
		private static final java.text.DecimalFormat formatter = new java.text.DecimalFormat("#.#########");
		private static void start () { if (t == 0) t = millis(); }
		private static void append (java.util.function.Consumer<Object> f, java.util.function.Consumer<Object> g, final Object o) {
			if (o.getClass().isArray()) {
				int len = java.lang.reflect.Array.getLength(o);
				for (int i = 0; i < len; ++i)
					f.accept(java.lang.reflect.Array.get(o, i));
			}
			else if (o instanceof Iterable<?>)
				((Iterable<?>)o).forEach(f::accept);
			else
				g.accept(o instanceof Double ? formatter.format(o) : o);
		}
		private static void append (final StringBuilder b, Object o, final String delim) {
			append(x -> { append(b, x, delim); }, x -> b.append(delim).append(x), o);
		}
		private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out);
		private static void print (Object o, Object ... A) {
			pw.println(build(o, A));
			if (DEBUG)
				pw.flush();
		}
		private static void err (Object o, Object ... A) { System.err.println(build(o, A)); }
		private static boolean DEBUG;
		private static void write (Object o) {
			err(o, '(', time(), ')');
			if (!DEBUG)
				pw.println(o);
		}
		private static void exit () {
			IOUtils.pw.close();
			System.out.flush();
			err("------------------");
			err(time());
			System.exit(0);
		}
		private static long t;
		private static long millis () { return System.currentTimeMillis(); }
		private static String time () { return "Time: " + (millis() - t) / 1000.0; }
		private static void run (int N) {
			try { DEBUG = System.getProperties().containsKey("DEBUG"); }
			catch (Throwable t) {}

			for (int n = 1; n <= N; ++n) {
				Object res = new E().solve();
				if (res != null)
					write("Case #" + n + ": " + build(res));
			}
			exit();
		}
	}
	////////////////////////////////////////////////////////////////////////////////////
	public static void main (String[] args) {
		init();
		int N = ONE_TEST_CASE ? 1 : sc.nextInt();
		IOUtils.run(N);
	}
}


/**
 * @author derrick20
 */

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

public class TopScorer {
    public static void main(String[] args) throws Exception {
        FastScanner sc = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);

        int P = sc.nextInt();
        int S = sc.nextInt();
        int R = sc.nextInt();
        // it should go up to s + p - 1, 5099, but let's be safe
        int MAX = (int) 1e5; // todo change this!
        fact = new long[MAX + 1];
        invFact = new long[MAX + 1];
        fact[0] = 1;
        invFact[0] = 1;
        for (int i = 1; i <= MAX; i++) {
            fact[i] = ((long) i * fact[i - 1]) % mod;
            invFact[i] = inv(fact[i]);
        }

        if (P == 1) {
            out.println(1);
        } else {
            // O(SP^2) = 5*10^7
            long wins = 0;
            long total = 0;
            for (int x = R; x <= S; x++) {
                // l = group that gets x
                // the remaining players P - 1 - l must get < x.
                for (int l = 0; P - 1 - l >= 0 && S - x - l * x >= 0; l++) {
                    int players = P - 1 - l;
                    int balls = S - x - l * x;
//                    System.out.println("Forced " + l + " other players to have exactly " + x + " balls");
//                    System.out.println("Remaining: players = " + players + " balls = " + balls);
                    long prob = (choose(P - 1, l) * f(players, balls, x)) % mod;
                    // prob of having this number of x's for players, then given
                    // that, the probability of winning is uniform among all x players
                    long contrib = (inv(l + 1) * prob) % mod;
                    wins = (wins + contrib) % mod;
//                    System.out.println("Prob: " + prob + " Contrib: " + contrib);
//                    System.out.println();
                }
                long ways = choose(S - x + P - 2, P - 2);
//                System.out.println("Ways for x = " + x + " = " + ways);
//                System.out.println("----------");
                total = (total + ways) % mod;
            }
            // we have now counted the number of winning states (scaling
            // with the f function). The probability is this divided by total
            // states.
            long prob = (wins * inv(total)) % mod;
            out.println(prob);
        }
        out.close();
    }

    // todo SET THE MOD
    static long mod = 998244353;
    static long[] fact, invFact;

    // f returns probability that with these parameters, we get an assignment
    // where all have < x balls.
    static long f(int players, int balls, int x) {
        // if there are no players, there MUST BE only 1 way.
        if (players == 0) {
//            ASSERT(balls <= x, "Gave impossible amt");
            return (balls <= x) ? 1 : 0;
        }
        long total = choose(balls + players - 1, players - 1);
        long complement = 0;
        int sign = 1;
        for (int k = 1; k <= players && balls - k * x >= 0; k++) {
            long amt = (choose(players, k) * choose(balls - k * x + players - 1, players - 1)) % mod;
            complement = (complement + sign * amt) % mod;
            sign *= -1;
        }
//        System.out.println("Ways for (players, balls) = " + players + " " + balls + ": Total " + total + ", Complement: " + complement);
        long ans = (total - complement + mod) % mod;
//        ans = (ans * inv(total)) % mod; // probability
        return ans;
    }

    static long choose(int n, int k) {
        ASSERT(k <= n, "Invalid choose");
        long ans = (fact[n] * invFact[n - k]) % mod;
        return (ans * invFact[k]) % mod;
    }

    static long inv(long x) {
        return fastExpo(x, mod - 2);
    }

    static long fastExpo(long x, long k) {
        long ans = 1;
        long bit = x;
        while (k > 0) {
            if (k % 2 == 1) {
                ans = (bit * ans) % mod;
            }
            bit = (bit * bit) % mod;
            k /= 2;
        }
        return ans;
    }

    static class FastScanner {
        private int BS = 1 << 16;
        private char NC = (char) 0;
        private byte[] buf = new byte[BS];
        private int bId = 0, size = 0;
        private char c = NC;
        private double cnt = 1;
        private BufferedInputStream in;

        public FastScanner() {
            in = new BufferedInputStream(System.in, BS);
        }

        public FastScanner(String s) {
            try {
                in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
            } catch (Exception e) {
                in = new BufferedInputStream(System.in, BS);
            }
        }

        private char getChar() {
            while (bId == size) {
                try {
                    size = in.read(buf);
                } catch (Exception e) {
                    return NC;
                }
                if (size == -1) return NC;
                bId = 0;
            }
            return (char) buf[bId++];
        }

        public int nextInt() {
            return (int) nextLong();
        }

        public int[] nextInts(int N) {
            int[] res = new int[N];
            for (int i = 0; i < N; i++) {
                res[i] = (int) nextLong();
            }
            return res;
        }

        public long[] nextLongs(int N) {
            long[] res = new long[N];
            for (int i = 0; i < N; i++) {
                res[i] = nextLong();
            }
            return res;
        }

        public long nextLong() {
            cnt = 1;
            boolean neg = false;
            if (c == NC) c = getChar();
            for (; (c < '0' || c > '9'); c = getChar()) {
                if (c == '-') neg = true;
            }
            long res = 0;
            for (; c >= '0' && c <= '9'; c = getChar()) {
                res = (res << 3) + (res << 1) + c - '0';
                cnt *= 10;
            }
            return neg ? -res : res;
        }

        public double nextDouble() {
            double cur = nextLong();
            return c != '.' ? cur : cur + nextLong() / cnt;
        }

        public double[] nextDoubles(int N) {
            double[] res = new double[N];
            for (int i = 0; i < N; i++) {
                res[i] = nextDouble();
            }
            return res;
        }

        public String next() {
            StringBuilder res = new StringBuilder();
            while (c <= 32) c = getChar();
            while (c > 32) {
                res.append(c);
                c = getChar();
            }
            return res.toString();
        }

        public String nextLine() {
            StringBuilder res = new StringBuilder();
            while (c <= 32) c = getChar();
            while (c != '\n') {
                res.append(c);
                c = getChar();
            }
            return res.toString();
        }

        public boolean hasNext() {
            if (c > 32) return true;
            while (true) {
                c = getChar();
                if (c == NC) return false;
                else if (c > 32) return true;
            }
        }
    }

    static void ASSERT(boolean assertion, String message) {
        if (!assertion) throw new AssertionError(message);
    }
}


import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
public class E {
  public static int mod = 998244353;
  public static int[] fact;
    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        // Scanner scan = new Scanner(System.in);
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        // int n = Integer.parseInt(bf.readLine());
        StringTokenizer st = new StringTokenizer(bf.readLine());
        // int[] a = new int[n]; for(int i=0; i<n; i++) a[i] = Integer.parseInt(st.nextToken());
        int p = Integer.parseInt(st.nextToken());
        int s = Integer.parseInt(st.nextToken());
        int r = Integer.parseInt(st.nextToken());

        long PIE = 0; // ways of someone >= r;
        int sign = 1;
        fact = new int[6001];
        fact[0] = 1;
        for(int i=1; i<=6000; i++) {
          fact[i] = (int)(1L*fact[i-1]*i % mod);
        }
        for(int i=1; i<=p; i++) {

          if(i < p) PIE += sign*(1L*choose(p, i)*choose(s - i*r + p-i-1, p-i-1) % mod);
          else PIE += sign*1;
          PIE += mod;
          PIE %= mod;

          sign = -1*sign;
        }

        long ways_first = choose(s-r+p-2, p-2) % mod;
        long ans = frac((int)PIE, (int)((1L * ways_first * p) % mod));
        out.println(ans);

        // int n = scan.nextInt();

        out.close(); System.exit(0);
    }
    public static int exp(int base, int e) {
      if(e == 0) return 1;
      if(e == 1) return base;
      int val = exp(base, e/2);
      int ans = (int)(1L*val*val % mod);
      if(e % 2 == 1)
        ans = (int)(1L*ans*base % mod);
      return ans;
    }
    public static int inv(int base) {
      return exp(base, mod-2);
    }
    public static long frac(int p, int q) {
      return (1L*p*inv(q) % mod);
    }
    public static long choose(int a, int b) {
      if(a<b) return 0;
      if(b < 0) return 0;
      return frac(fact[a],(int)(1L*fact[b]*fact[a-b] % mod));
    }
}


//package vk.cup2021.quals;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Optional;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class E {
    private final FastScanner fastScanner;
    private final PrintWriter printWriter;

    public E(FastScanner fastScanner, PrintWriter printWriter) {
        this.fastScanner = fastScanner;
        this.printWriter = printWriter;
    }

    public static void main(String[] args) {
        try (FastScanner fastScanner = new FastScanner(System.in);
             PrintWriter printWriter = new PrintWriter(System.out)
        ) {
            E e = new E(fastScanner, printWriter);
            e.solve();
        } catch (Exception exception) {
            throw new RuntimeException(exception);
        }
    }

    private static void mergeSort(int l, int r, MegaComparator megaComparator, int[] a, int[] b) {
        if (r - l <= 1) {
            return;
        }
        int m = (l + r) / 2;
        mergeSort(l, m, megaComparator, a, b);
        mergeSort(m, r, megaComparator, a, b);
        int i = l;
        int j = m;
        int k = l;
        while (i < m && j < r) {
            if (megaComparator.compare()) {
                b[k] = a[i];
                i++;
            } else {
                b[k] = a[j];
                j++;
            }
            k++;
        }
        while (i < m) {
            b[k] = a[i];
            i++;
            k++;
        }
        while (j < r){
            b[k] = a[j];
            j++;
            k++;
        }
        System.arraycopy(b, l, a, l, r - l);
    }

    private static Optional<int[]> tryToSolve(int permutationSize, String s) {
        MegaComparator megaComparator = new MegaComparator(s);
        int[] a = IntStream.range(0, permutationSize).toArray();
        int[] b = new int[permutationSize];
        mergeSort(0, permutationSize, megaComparator, a, b);
        return Optional.of(a)
                .filter(perm -> megaComparator.allDone())
                .map(E::getPermutation);
    }

    private static int[] getPermutation(int[] a) {
        int[] result = new int[a.length];
        for (int i = 0; i < a.length; i++) {
            result[a[i]] = i + 1;
        }
        return result;
    }

    private void solve() throws Exception {
        String s = fastScanner.next();
        int[] result = tryToSolve(16, s).orElseThrow(() -> new RuntimeException("GG"));
        printWriter.println(16);
        printWriter.println(Arrays.stream(result).mapToObj(String::valueOf).collect(Collectors.joining(" ")));
    }

    private static class MegaComparator {
        private final String data;
        private int pointer;

        public MegaComparator(String data) {
            this.data = data;
            this.pointer = 0;
        }

        public boolean allDone() {
            return pointer == data.length();
        }

        public boolean compare() {
            return data.charAt(pointer++) == '0';
        }
    }

    private static class FastScanner implements Closeable {
        private final BufferedReader bufferedReader;
        private StringTokenizer stringTokenizer;

        public FastScanner(InputStream inputStream) {
            this(new BufferedReader(new InputStreamReader(inputStream)));
        }

        public FastScanner(BufferedReader bufferedReader) {
            this.bufferedReader = bufferedReader;
        }

        public String next() throws IOException {
            while (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
                String line = bufferedReader.readLine();
                if (line == null) {
                    return null;
                }
                stringTokenizer = new StringTokenizer(line);
            }
            return stringTokenizer.nextToken();
        }

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

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        @Override
        public void close() throws IOException {
            this.bufferedReader.close();
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.*;

public class Template {

    static BufferedReader br;
    static PrintWriter out;
    static StringTokenizer st;
    static boolean[][] e = new boolean[20][20];
    static boolean[] used = new boolean[20];
    static List<Integer> ans = new ArrayList<>();

    static int solve(List<Integer> arr, int l, int r, int index, String flags) {
        int m = (l + r) >> 1;

        if(l == r - 1) {
            return index;
        }

        index = solve(arr, l, m, index, flags);
        index = solve(arr, m, r, index, flags);
        int i = l;
        int j = m;
        List<Integer> tmp = new LinkedList<>();
        while (i < m && j < r) {
            if (flags.charAt(index++) == '0') {
                e[arr.get(i)][arr.get(j)] = true;
                tmp.add(arr.get(i));
                i += 1;
            }
            else {
                e[arr.get(j)][arr.get(i)] = true;
                tmp.add(arr.get(j));
                j++;
            }
        }
        for (int k = 0; k < tmp.size(); k++) {
            arr.set(l + k, tmp.get(k));
        }
        return index;
    }

    static void dfs (int v) {
        used[v] = true;
//        for (int i=0; i<g[v].size(); ++i) {
//            int to = g[v][i];
//            if (!used[to])
//                dfs (to);
//        }
        for (int j = 0; j < 16; j++) {
            if(e[v][j] && !used[j]) {
                dfs (j);
            }
        }
        ans.add (v);
    }

    static void topological_sort() {
        for (int i=0; i<20; ++i)
            used[i] = false;
        ans.clear();
        for (int i=0; i<16; ++i)
            if (!used[i])
                dfs (i);
    }

    public static void main(String[] args) throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new OutputStreamWriter(System.out));
        // br = new BufferedReader(new FileReader("in.txt"));
        // out = new PrintWriter(new FileWriter("out.txt"));

        String flags = next();
        List<Integer> arr = new ArrayList<>();
        for(int i = 0; i < 16; i++) {
            arr.add(i);
        }
        solve(arr, 0, 16, 0, flags);
        topological_sort();

        out.println(ans.size());
        for(int i = ans.size() - 1; i >= 0; i--) {
            out.print(ans.get(i) + 1);
            out.print(" ");
        }
        out.close();
    }

    static String next() throws IOException {
        while (st == null || !st.hasMoreTokens())
            st = new StringTokenizer(br.readLine().trim());
        return st.nextToken();
    }

    static long readLong() throws IOException {
        return Long.parseLong(next());
    }

    static int readInt() throws IOException {
        return Integer.parseInt(next());
    }

    static double readDouble() throws IOException {
        return Double.parseDouble(next());
    }

    static char readCharacter() throws IOException {
        return next().charAt(0);
    }

    static String readLine() throws IOException {
        return br.readLine().trim();
    }
}