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.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * stescobedo
 */
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);
        FNezzarAndChocolateBars solver = new FNezzarAndChocolateBars();
        solver.solve(1, in, out);
        out.close();
    }

    static class FNezzarAndChocolateBars {
        static final int MAXN = 2048;
        static final int modulo = 998244353;

        public int add(int x, int y) {
            x += y;
            if (x >= modulo) x -= modulo;
            return x;
        }

        public int subtract(int x, int y) {
            x -= y;
            if (x < 0) x += modulo;
            return x;
        }

        public int multiply(int x, int y) {
            return (int) ((x * 1L * y) % modulo);
        }

        public int power(int x, long y) {
            int ans = 1;
            for (; y > 0; y >>= 1, x = (int) ((x * 1L * x) % modulo))
                if (y % 2 == 1) ans = (int) ((ans * 1L * x) % modulo);
            return ans;
        }

        public int inverse(int x) {
            return power(x, modulo - 2);
        }

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int[] fact = new int[MAXN];
            int[] ifact = new int[MAXN];
            fact[0] = ifact[0] = 1;
            for (int i = 1; i < MAXN; i++) {
                fact[i] = multiply(fact[i - 1], i);
                ifact[i] = inverse(fact[i]);
            }
            int n = in.nextInt(), k = in.nextInt();
            int[] l = in.readIntArray(n);
            int[][][] dp = new int[2][MAXN][n + 1];
            dp[1][0][0] = 1;
            int s = 0;

            for (int p = 0; p < n; p++) {
                int L = l[p];
                int invL = inverse(L);
                int[] coeffs = new int[L / k + 1];
                int[] coeffs2 = new int[L / k + 1];
                for (int i = 0; i <= L / k; i++) {
                    if (k * i == L) continue;
                    int z = ifact[i];
                    if (i % 2 == 1) z = subtract(0, z);
                    coeffs[i] = multiply(z, power(L - k * i, i));

                    if (i >= 1) {
                        coeffs2[i] = multiply(z, multiply(i, power(L - k * i, i - 1)));
                    }
                }
                int r = p & 1;
                int h = r ^ 1;
                for (int i = 0; i <= s / k; i++) Arrays.fill(dp[r][i], 0);
                for (int i = 0; i <= s / k; i++)
                    for (int j = 0; j <= p; j++)
                        if (dp[h][i][j] != 0) {
                            int value = dp[h][i][j];
                            for (int t = 0; t <= L / k; t++) {
                                dp[r][i + t][j] = add(dp[r][i + t][j], multiply(value, coeffs[t]));
                                if (t > 0) {
                                    dp[r][i + t - 1][j + 1] = add(dp[r][i + t - 1][j + 1], multiply(value, coeffs2[t]));
                                }
                            }
                        }
                s += L;
            }
            int answer = 0;
            for (int i = 0; i <= s / k; i++)
                for (int r = 0; r <= n; r++) {
                    int value = dp[(n - 1) & 1][i][r];
                    int j = i + r;
                    if (j == 0) continue;
                    int temp = multiply(fact[i], inverse(power(k * j, i + 1)));
                    answer = add(answer, multiply(value, temp));
                }
            out.println(multiply(subtract(0, s), answer));
        }

    }

    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[] readIntArray(int size) {
            int[] array = new int[size];
            for (int i = 0; i < size; i++) {
                array[i] = readInt();
            }
            return array;
        }

        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 nextInt() {
            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 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 {
            public boolean isSpaceChar(int ch);

        }

    }

    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 println(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
            writer.print('\n');
        }

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

    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class _LiftLevel5E {

	static boolean[][] locked;
	static int[][] board;
	static int[][] solved;
	static int w, h;
	static ArrayList<String> answer=new ArrayList<>();

	public static void main(String[] args) {
		FastScanner fs=new FastScanner();
		h=fs.nextInt(); w=fs.nextInt();
		board=new int[w][h];
		solved=new int[w][h];
		locked=new boolean[w][h];
		for (int y=0; y<h; y++) {
			for (int x=0; x<w; x++) {
				board[x][y]=fs.nextInt();
				solved[x][y]=x+y*w+1;
			}
		}
		//solve ys [0, h-2)
		for (int yToSolveFor=0; yToSolveFor<h-2; yToSolveFor++) {
			for (int xToSolveFor=0; xToSolveFor<w-1; xToSolveFor++) {
				naiveMoveToXFirst(solved[xToSolveFor][yToSolveFor], xToSolveFor, yToSolveFor);
				locked[xToSolveFor][yToSolveFor]=true;
			}
			//now handle the rightmost position
			if (board[w-1][yToSolveFor]==solved[w-1][yToSolveFor]) {
				locked[w-1][yToSolveFor]=true;
				continue;
			}
			naiveMoveToXFirst(solved[w-1][yToSolveFor], w-1, h-1);
			hardCW4(w-2, yToSolveFor);
			naiveMoveToXFirst(solved[w-1][yToSolveFor], w-1, yToSolveFor+1);
			hardCCW4(w-2, yToSolveFor);
			locked[w-2][yToSolveFor]=locked[w-1][yToSolveFor]=true;
		}
//		print(board);

		//now we only have the last two ys left
		for (int x=0; x<w-2; x++) {
//			print(board);
			naiveMoveToXFirst(solved[x][h-1], x, h-1);
			if (solved[x][h-2]==board[x][h-2]) {
				locked[x][h-1] = locked[x][h-2]=true;
				continue;
			}
			locked[x][h-2] = true;
			naiveMoveToXFirst(solved[x][h-2], w-1, h-1);
			hardCW4(x, h-2);
			naiveMoveToXFirst(solved[x][h-2], x+1, h-2);
			hardCCW4(x, h-2);
			locked[x][h-1]=true;
		}

		//TODO: handle the last 4 spaces
		while (board[w-2][h-2]!=solved[w-2][h-2]) {
			hardCW4(w-2, h-2);
		}
		int target=solved[w-1][h-2];
		if (board[w-1][h-2]==target) {

		}
		else if (board[w-2][h-1]==target) {
			swapBottom2();
			swapRight2();
		}
		else {
			swapRight2();
		}
		target=solved[w-2][h-1];
		if (board[w-2][h-1]==target) {

		}
		else {
			swapBottom2();
		}
		System.out.println(answer.size());
		for (String s:answer) {
			System.out.println(s);
		}
//		print(board);
	}

	static void sixCycle() {
		hardCCW4(w-2, h-2);
		hardCCW4(w-3, h-2);
		moveNoWarnings(w-3, h-2, w-2, h-2, w-1, h-2,
				w-1, h-1, w-2, h-1, w-3, h-1);
	}

	static void swapRight2() {
		hardCCW4(w-2, h-2);
		sixCycle();
		hardCW4(w-2, h-2);
	}

	static void swapLeft2() {
		hardCW4(w-2, h-2);
		sixCycle();
		hardCCW4(w-2, h-2);
	}

	static void swaptTop2() {
		sixCycle();
	}

	static void swapBottom2() {
		hardCW4(w-2, h-2);
		hardCW4(w-2, h-2);
		sixCycle();
		hardCCW4(w-2, h-2);
		hardCCW4(w-2, h-2);
	}

	static boolean movable(int x, int y) {
		if (x< 0 || x>=locked.length || y<0 || y>=locked[x].length) return false;
		return !locked[x][y];
	}

	//moves x first then y
	static void naiveMoveToXFirst(int toMove, int targetX, int targetY) {
		Point curPos=locationOf(toMove);
		int curX=curPos.x;
		int curY=curPos.y;
		while (curX<targetX) {
			moveRight(curX, curY);
			curX++;
		}
		while (curX>targetX) {
			moveLeft(curX, curY);
			curX--;
		}
		while (curY<targetY) {
			moveDown(curX, curY);;
			curY++;
		}
		while (curY>targetY) {
			moveUp(curX, curY);
			curY--;
		}
	}

	static void moveLeft(int x, int y) {
		if (!movable(x, y) || !movable(x-1, y)) {
			throw null;
		}
		if (movable(x-1, y+1) && movable(x, y+1)) {
			move(x, y, x-1, y, x-1, y+1, x, y+1);
			return;
		}
		if (movable(x-1, y-1) && movable(x-1, y-1)) {
			move(x, y, x-1, y, x-1, y-1, x, y-1);
			return;
		}
		throw null;
	}

	static void moveRight(int x, int y) {
		if (!movable(x, y) || !movable(x+1, y)) {
			throw null;
		}
		if (movable(x+1, y+1) && movable(x, y+1)) {
			move(x, y, x+1, y, x+1, y+1, x, y+1);
			return;
		}
		if (movable(x+1, y-1) && movable(x, y-1)) {
			move(x, y, x+1, y, x+1, y-1, x, y-1);
			return;
		}
//		System.out.println("Trying to move right on pos: "+x+" "+y+" but it is impossible");
//		print(locked);
		throw null;
	}

	static void moveDown(int x, int y) {
		if (!movable(x, y) || !movable(x, y+1)) {
			throw null;
		}
		if (movable(x-1, y+1) && movable(x-1, y)) {
			move(x, y, x, y+1, x-1, y+1, x-1, y);
			return;
		}
		if (movable(x+1, y+1) && movable(x+1, y)) {
			move(x, y, x, y+1, x+1, y+1, x+1, y);
			return;
		}
		throw null;
	}

	static void moveUp(int x, int y) {
		if (!movable(x, y) || !movable(x, y-1)) {
			throw null;
		}
		if (movable(x-1, y-1) && movable(x-1, y)) {
			move(x, y, x, y-1, x-1, y-1, x-1, y);
			return;
		}
		if (movable(x+1, y-1) && movable(x+1, y)) {
			move(x, y, x, y-1, x+1, y-1, x+1, y);
			return;
		}
		throw null;
	}

	static void move(int ...input) {
		if (input.length%2!=0) throw null;
		int[] xs=new int[input.length/2], ys=new int[input.length/2];
		for (int i=0; i<input.length; i+=2) {
			xs[i/2]=input[i];
			ys[i/2]=input[i+1];
		}
		int nPoints=input.length/2;
		for (int i=0; i<nPoints; i++) {
			if (!movable(xs[i], ys[i])) throw null;
		}
		int[] old=new int[nPoints];
		for (int i=0; i<nPoints; i++) old[i]=board[xs[i]][ys[i]];
		for (int i=0; i<nPoints; i++) board[xs[i]][ys[i]] = old[(i-1+nPoints)%nPoints];
		StringBuilder sb=new StringBuilder(nPoints+" ");
		for (int i:old) {
			sb.append(i+" ");
		}
		answer.add(sb.toString());
	}

	static void moveNoWarnings(int ...input) {
		if (input.length%2!=0) throw null;
		int[] xs=new int[input.length/2], ys=new int[input.length/2];
		for (int i=0; i<input.length; i+=2) {
			xs[i/2]=input[i];
			ys[i/2]=input[i+1];
		}
		int nPoints=input.length/2;
		int[] old=new int[nPoints];
		for (int i=0; i<nPoints; i++) old[i]=board[xs[i]][ys[i]];
		for (int i=0; i<nPoints; i++) board[xs[i]][ys[i]] = old[(i-1+nPoints)%nPoints];
		StringBuilder sb=new StringBuilder(nPoints+" ");
		for (int i:old) {
			sb.append(i+" ");
		}
		answer.add(sb.toString());
	}

	static void hardCW4(int topLeftX, int topLeftY) {
		moveNoWarnings(topLeftX, topLeftY, topLeftX+1, topLeftY, topLeftX+1, topLeftY+1, topLeftX, topLeftY+1);
	}

	static void hardCCW4(int topLeftX, int topLeftY) {
		moveNoWarnings(topLeftX, topLeftY, topLeftX, topLeftY+1, topLeftX+1, topLeftY+1, topLeftX+1, topLeftY);
	}

	static Point locationOf(int i) {
		for(int x=0; x<w; x++) {
			for (int y=0; y<h; y++) {
				if (board[x][y]==i) return new Point(x, y);
			}
		}
//		System.out.println("Couldn't find location of "+i+" in ");
//		print(board);
		throw null;
	}

	static class FastScanner {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=new StringTokenizer("");
		String next() {
			while (!st.hasMoreElements()) {
				try {
					st=new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

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

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

	static void print(int[][] board) {
		for (int y=0; y<board[0].length; y++) {
			for (int x=0; x<board.length; x++) System.out.print(board[x][y]+" ");
			System.out.println();
		}
		System.out.println();
	}
	static void print(boolean[][] board) {
		for (int y=0; y<board[0].length; y++) {
			for (int x=0; x<board.length; x++) System.out.print((board[x][y]?"*":"_")+" ");
			System.out.println();
		}
		System.out.println();
	}
}


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

public class p926J {
	public static void main(String[] args) throws IOException {
		BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		StringTokenizer st;
		int times = Integer.parseInt(f.readLine());
		IntervalList list = new IntervalList();
		while(times-- > 0)
		{
			st = new StringTokenizer(f.readLine());
			int s = Integer.parseInt(st.nextToken());
			int e = Integer.parseInt(st.nextToken());
			list.add(s, e);
			out.println(list.size());
		}
		out.close();
	}

	static class IntervalList
	{
		public TreeSet<Interval> set;
		public IntervalList()
		{
			set = new TreeSet<Interval>();
		}

		public void add(int s, int e)
		{
			Iterator<Interval> iter = set.tailSet(new Interval(s, s), true).iterator();
			while(iter.hasNext())
			{
				Interval i = iter.next();
				if(i.s > e)
					break;
				if(i.s < s)
					s = i.s;
				if(i.e > e)
					e = i.e;
				iter.remove();
			}
			set.add(new Interval(s, e));
		}

		public int size()
		{
			return set.size();
		}
	}

	static class Interval implements Comparable<Interval>
	{
		int s, e;
		public Interval(int s, int e)
		{
			this.s = s;
			this.e = e;
		}

		public int compareTo(Interval i)
		{
			return e - i.e;
		}

		public String toString()
		{
			return s + " " + e;
		}
	}
}


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

/**
 * @author Don Li
 */
public class Pollywog {

    long INF = (long) 2e18;

    void solve() {
        int x = in.nextInt(), k = in.nextInt(), n = in.nextInt(), q = in.nextInt();
        int[] c = new int[k + 1];
        for (int i = 1; i <= k; i++) c[i] = in.nextInt();

        int[][] stones = new int[q + 1][2];
        for (int i = 0; i < q; i++) {
            int p = in.nextInt() - 1, w = in.nextInt();
            stones[i][0] = p;
            stones[i][1] = w;
        }
        stones[q][0] = n; stones[q][1] = 0;
        Arrays.sort(stones, Comparator.comparingInt(a -> a[0]));

        int id = 0;
        int[] state_to_id = new int[1 << k];
        int[] id_to_state = new int[1 << k];
        for (int i = 0; i < 1 << k; i++) {
            if (Integer.bitCount(i) == x) {
                id_to_state[id] = i;
                state_to_id[i] = id;
                id++;
            }
        }

        long[][][] basepow = new long[60][id][id];
        fill(basepow, INF);
        for (int i = 0; i < id; i++) {
            int state = id_to_state[i];
            if ((state & 1 << (k - 1)) == 0) {
                basepow[0][i][state_to_id[state << 1]] = 0;
                continue;
            }
            for (int j = 1; j <= k; j++) {
                int nstate = state ^ 1 << (k - 1);
                nstate <<= 1;
                if ((nstate & 1 << (k - j)) > 0) continue; // skip when this position is occupied
                basepow[0][i][state_to_id[nstate | 1 << (k - j)]] = c[j];
            }
        }
        for (int level = 1; level < basepow.length; level++) {
            basepow[level] = mult(basepow[level - 1], basepow[level - 1]);
        }

        long[][] cost = new long[id][id];
        fill(cost, INF);
        int start = (1 << k) - (1 << (k - x));
        cost[state_to_id[start]][state_to_id[start]] = 0;

        int cpos = 0, sidx = 0;
        while (cpos < n - x) {
            while (cpos > stones[sidx][0]) sidx++;

            if (cpos + k >= stones[sidx][0]) {
                long[][] base = new long[id][id];
                fill(base, INF);
                for (int i = 0; i < id; i++) {
                    int state = id_to_state[i];
                    if ((state & 1 << (k - 1)) == 0) {
                        base[i][state_to_id[state << 1]] = 0;
                        continue;
                    }
                    for (int j = 1; j <= k; j++) {
                        int nstate = state ^ 1 << (k - 1);
                        nstate <<= 1;
                        if ((nstate & 1 << (k - j)) > 0) continue;
                        int tcost = c[j];
                        for (int a = 0; a < 2*k; a++) {
                            if (sidx + a < stones.length && cpos + j == stones[sidx + a][0]) {
                                tcost += stones[sidx + a][1];
                            }
                        }
                        base[i][state_to_id[nstate | 1 << (k - j)]] = tcost;
                    }
                }
                cost = mult(cost, base);
                cpos++;
            } else {
                long dist = (stones[sidx][0] - k) - cpos;
                for (int i = 0; i < 60; i++) {
                    if ((dist & (1L << i)) > 0) {
                        cost = mult(cost, basepow[i]);
                    }
                }
                cpos += dist;
            }
        }

        out.println(cost[state_to_id[start]][state_to_id[start]]);
    }

    long[][] mult(long[][] a, long[][] b) {
        int n = a.length;
        long[][] c = new long[n][n];
        fill(c, INF);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    c[i][j] = Math.min(c[i][j], a[i][k] + b[k][j]);
                }
            }
        }
        return c;
    }

    void fill(long[][][] a, long val) {
        for (long[][] x : a) fill(x, val);
    }

    void fill(long[][] a, long val) {
        for (long[] x : a) Arrays.fill(x, val);
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new Pollywog().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

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

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Andy Phan
 */
public class p1173e {
    static int MOD = 998244353;
    static int n;
    static int m;
    static long[] invert;
    static long[][] f;
    static long[][] g;
    static boolean[][] df;
    static boolean[][] dg;
    static int[] sum;
    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = in.nextInt();
        m = in.nextInt();
        invert = new long[2*m];
        int[] like = new int[n];
        sum = new int[2];
        int[] weight = new int[n];
        for(int i = 0; i < n; i++) like[i] = in.nextInt();
        for(int i = 0; i < n; i++) {
            weight[i] = in.nextInt();
            sum[1-like[i]] += weight[i];
        }
        for(int i = -(m-1); i < m; i++) invert[i+m-1] = modInv(sum[0]+sum[1]+i, MOD);
        f = new long[m][m];
        g = new long[m][m];
        df = new boolean[m][m];
        dg = new boolean[m][m];
        for(int i = 0; i < n; i++) if(like[i] == 0) out.println((g(0, 0)*weight[i])%MOD); else out.println((f(0, 0)*weight[i])%MOD);
        out.close();
    }

    static long f(int i, int j) {
        if(i+j == m) return 1;
        if(df[i][j]) return f[i][j];
        df[i][j] = true;
        return f[i][j] = (((((sum[0]+i+1)*invert[i-j+m-1])%MOD)*f(i+1, j))%MOD+((((sum[1]-j)*invert[i-j+m-1])%MOD)*f(i, j+1))%MOD)%MOD;
    }

    static long g(int i, int j) {
        if(i+j == m) return 1;
        if(dg[i][j]) return g[i][j];
        dg[i][j] = true;
        return g[i][j] = (((((sum[0]+i)*invert[i-j+m-1])%MOD)*g(i+1, j))%MOD+((((sum[1]-j-1)*invert[i-j+m-1])%MOD)*g(i, j+1))%MOD)%MOD;
    }

    //@
    static long gcd(long a, long b) { return b == 0 ? a : gcd(b, a % b); }
    static long lcm(long a, long b) { return a / gcd(a, b) * b; }

    //@
    // Computes the modular inverse of x
    // Returns 0 if the GCD of x and mod is not 1
    // O(log n)  :  Can be converted to use BigIntegers
    static long modInv(long x, long mod) {
            if(x == 1) return 1;
            if(gcd(x, mod) != 1) return 0;
            long r = mod % x;
            return (modInv(r, x % r, 0, 1, mod / x, x / r)+mod)%mod;
    }

    static long modInv(long a, long b, long y0, long y1, long q0, long q1) {
            long y2 = y0 - y1*q0;
            return b == 0 ? y2 : modInv(b, a % b, y1, y2, q1, a / b);
    }
    static class FS {
        BufferedReader in;
        StringTokenizer t;

        public FS(InputStream i) {
            in = new BufferedReader(new InputStreamReader(i));
        }

        public String next() {
            try {
                while(t == null || !t.hasMoreElements()) {
                    t = new StringTokenizer(in.readLine());
                }
            } catch(Exception e) {}
            return t.nextToken();
        }

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