An online contest will soon be held on ForceCoders, a large competitive programming platform. The authors have prepared n problems; and since the platform is very popular, 998244351 coder from all over the world is going to solve them.

For each problem, the authors estimated the number of people who would solve it: for the i-th problem, the number of accepted solutions will be between l_i and r_i, inclusive.

The creator of ForceCoders uses different criteria to determine if the contest is good or bad. One of these criteria is the number of inversions in the problem order. An inversion is a pair of problems (x, y) such that x is located earlier in the contest (x < y), but the number of accepted solutions for y is strictly greater.

Obviously, both the creator of ForceCoders and the authors of the contest want the contest to be good. Now they want to calculate the probability that there will be no inversions in the problem order, assuming that for each problem i, any integral number of accepted solutions for it (between l_i and r_i) is equally probable, and all these numbers are independent.

Input

The first line contains one integer n (2 ≤ n ≤ 50) — the number of problems in the contest.

Then n lines follow, the i-th line contains two integers l_i and r_i (0 ≤ l_i ≤ r_i ≤ 998244351) — the minimum and maximum number of accepted solutions for the i-th problem, respectively.

Output

The probability that there will be no inversions in the contest can be expressed as an irreducible fraction x/y, where y is coprime with 998244353. Print one integer — the value of xy^{-1}, taken modulo 998244353, where y^{-1} is an integer such that yy^{-1} ≡ 1 (mod 998244353).

Examples

Input


3
1 2
1 2
1 2


Output


499122177


Input


2
42 1337
13 420


Output


578894053


Input


2
1 1
0 0


Output


1


Input


2
1 1
1 1


Output


1

Note

The real answer in the first test is 1/2.
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.util.Random;
import java.util.ArrayList;
import java.io.UncheckedIOException;
import java.util.List;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            FGoodContest solver = new FGoodContest();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class FGoodContest {
        Modular mod = new Modular(998244353);
        InverseNumber inverseNumber = new InverseNumber(100, mod);
        Power power = new Power(mod);

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            Interval[] intervals = new Interval[n];
            IntegerList list = new IntegerList(n * 2);
            for (int i = 0; i < n; i++) {
                intervals[i] = new Interval(in.readInt(), in.readInt());
                list.add(intervals[i].l);
                list.add(intervals[i].r);
            }
            SequenceUtils.reverse(intervals, 0, intervals.length - 1);

            list.unique();
            List<Interval> allPossibleIntervals = new ArrayList<>(list.size() * 2);
            allPossibleIntervals.add(new Interval(list.first(), list.first()));
            for (int i = 1; i < list.size(); i++) {
                int last = list.get(i - 1);
                int cur = list.get(i);
                if (cur - last > 1) {
                    allPossibleIntervals.add(new Interval(last + 1, cur - 1));
                }
                allPossibleIntervals.add(new Interval(cur, cur));
            }

            Interval[] ranges = allPossibleIntervals.toArray(new Interval[0]);
            int m = ranges.length;
            int[][] dp = new int[m + 1][n + 1];
            dp[0][0] = 1;
            int[] comp = new int[n + 1];
            for (int i = 1; i <= m; i++) {
                for (int j = 0; j <= n; j++) {
                    comp[j] = nonStrictlyIncrementSequence(ranges[i - 1].length(), j);
                }
                for (int j = 0; j <= n; j++) {
                    dp[i][j] = mod.plus(dp[i][j], dp[i - 1][j]);
                    for (int k = j - 1; k >= 0; k--) {
                        if (!intervals[k].contain(ranges[i - 1])) {
                            break;
                        }
                        int contrib = dp[i - 1][k];
                        contrib = mod.mul(comp[j - k], contrib);
                        dp[i][j] = mod.plus(dp[i][j], contrib);
                    }
                }
            }

            // System.err.println(Arrays.deepToString(dp));
            int valid = dp[m][n];
            int total = 1;
            for (int i = 0; i < n; i++) {
                total = mod.mul(total, intervals[i].length());
            }

            int ans = valid;
            ans = mod.mul(ans, power.inverseByFermat(total));
            out.println(ans);
        }

        public int nonStrictlyIncrementSequence(int n, int k) {
            return composite(n - 1 + k, k);
        }

        public int composite(int n, int m) {
            if (n < m) {
                return 0;
            }
            return m == 0 ? 1 : mod.mul(mod.mul(n, inverseNumber.inverse(m)), composite(n - 1, m - 1));
        }

    }

    static class IntegerList implements Cloneable {
        private int size;
        private int cap;
        private int[] data;
        private static final int[] EMPTY = new int[0];

        public IntegerList(int cap) {
            this.cap = cap;
            if (cap == 0) {
                data = EMPTY;
            } else {
                data = new int[cap];
            }
        }

        public IntegerList(IntegerList list) {
            this.size = list.size;
            this.cap = list.cap;
            this.data = Arrays.copyOf(list.data, size);
        }

        public IntegerList() {
            this(0);
        }

        public void ensureSpace(int req) {
            if (req > cap) {
                while (cap < req) {
                    cap = Math.max(cap + 10, 2 * cap);
                }
                data = Arrays.copyOf(data, cap);
            }
        }

        private void checkRange(int i) {
            if (i < 0 || i >= size) {
                throw new ArrayIndexOutOfBoundsException("index " + i + " out of range");
            }
        }

        public int get(int i) {
            checkRange(i);
            return data[i];
        }

        public void add(int x) {
            ensureSpace(size + 1);
            data[size++] = x;
        }

        public void addAll(int[] x, int offset, int len) {
            ensureSpace(size + len);
            System.arraycopy(x, offset, data, size, len);
            size += len;
        }

        public void addAll(IntegerList list) {
            addAll(list.data, 0, list.size);
        }

        public void sort() {
            if (size <= 1) {
                return;
            }
            Randomized.shuffle(data, 0, size);
            Arrays.sort(data, 0, size);
        }

        public int first() {
            checkRange(0);
            return data[0];
        }

        public void unique() {
            if (size <= 1) {
                return;
            }

            sort();
            int wpos = 1;
            for (int i = 1; i < size; i++) {
                if (data[i] != data[wpos - 1]) {
                    data[wpos++] = data[i];
                }
            }
            size = wpos;
        }

        public int size() {
            return size;
        }

        public int[] toArray() {
            return Arrays.copyOf(data, size);
        }

        public String toString() {
            return Arrays.toString(toArray());
        }

        public boolean equals(Object obj) {
            if (!(obj instanceof IntegerList)) {
                return false;
            }
            IntegerList other = (IntegerList) obj;
            return SequenceUtils.equal(data, 0, size - 1, other.data, 0, other.size - 1);
        }

        public int hashCode() {
            int h = 1;
            for (int i = 0; i < size; i++) {
                h = h * 31 + Integer.hashCode(data[i]);
            }
            return h;
        }

        public IntegerList clone() {
            IntegerList ans = new IntegerList();
            ans.addAll(this);
            return ans;
        }

    }

    static class Power {
        final Modular modular;

        public Power(Modular modular) {
            this.modular = modular;
        }

        public int pow(int x, int n) {
            if (n == 0) {
                return modular.valueOf(1);
            }
            long r = pow(x, n >> 1);
            r = modular.valueOf(r * r);
            if ((n & 1) == 1) {
                r = modular.valueOf(r * x);
            }
            return (int) r;
        }

        public int inverseByFermat(int x) {
            return pow(x, modular.m - 2);
        }

    }

    static class Randomized {
        private static Random random = new Random();

        public static void shuffle(int[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                int tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

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

    }

    static class SequenceUtils {
        public static <T> void swap(T[] data, int i, int j) {
            T tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }

        public static <T> void reverse(T[] data, int l, int r) {
            while (l < r) {
                swap(data, l, r);
                l++;
                r--;
            }
        }

        public static boolean equal(int[] a, int al, int ar, int[] b, int bl, int br) {
            if ((ar - al) != (br - bl)) {
                return false;
            }
            for (int i = al, j = bl; i <= ar; i++, j++) {
                if (a[i] != b[j]) {
                    return false;
                }
            }
            return true;
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c);
            println();
            return this;
        }

        public FastOutput println() {
            cache.append(System.lineSeparator());
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class Interval {
        int l;
        int r;

        boolean contain(Interval other) {
            return l <= other.l && other.r <= r;
        }

        int length() {
            return r - l + 1;
        }

        public Interval(int l, int r) {
            this.l = l;
            this.r = r;
        }

        public String toString() {
            return String.format("[%d,%d]", l, r);
        }

    }

    static class InverseNumber {
        int[] inv;

        public InverseNumber(int[] inv, int limit, Modular modular) {
            this.inv = inv;
            inv[1] = 1;
            int p = modular.getMod();
            for (int i = 2; i <= limit; i++) {
                int k = p / i;
                int r = p % i;
                inv[i] = modular.mul(-k, inv[r]);
            }
        }

        public InverseNumber(int limit, Modular modular) {
            this(new int[limit + 1], limit, modular);
        }

        public int inverse(int x) {
            return inv[x];
        }

    }

    static class Modular {
        int m;

        public int getMod() {
            return m;
        }

        public Modular(int m) {
            this.m = m;
        }

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        public String toString() {
            return "mod " + m;
        }

    }
}

