import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.util.TreeMap;
public class E1113
{
    static class QN{
        int index;
        long sum;
        QN(int in,long an){
            index=in;
            sum=an;
        }
    }
    static class SegmentTree{
        long sum,pmin,lazy;
        int st,en;
        boolean rem;
        SegmentTree left,right;
        SegmentTree(int _st,int _en,long _v){
            st=_st;
            en=_en;
            lazy=_v;
            rem=true;
            sum=(en-st+1)*lazy;
            pmin=Math.min(lazy,sum);
        }
        long pmin(){
            return rem?(Math.min(lazy,(en-st+1)*lazy)):(pmin);
        }
        long sum(){
            return rem?((en-st+1)*lazy):(sum);
        }
        void update(int l,int r,long v){
            //completely outside
            if(l>en||r<st)
                return;
            //completely inside
            if(l<=st&&r>=en){
                //update lazy;
                lazy=v;
                rem=true;
                return;
            }
            //partial cover
            lazyPropagate();
            left.update(l, r, v);
            right.update(l, r, v);
            sum=left.sum()+right.sum();
            pmin=Math.min(left.pmin(),left.sum()+right.pmin());
            return;
        }
        void lazyPropagate(){
            if(left==null){
                int mid=(st+en)/2;
                left=new SegmentTree(st,mid,lazy);
                right=new SegmentTree(mid+1,en,lazy);
            }else if(rem){
                left.lazy=lazy;
                right.lazy=lazy;
                left.rem=true;
                right.rem=true;
            }
            if(rem){
                sum=(en-st+1)*lazy;
                pmin=Math.min(lazy,sum);
            }
            rem=false;
        }
        /**returns least index which has value <= given value**/
        QN query(int l,int r,long v,long su){
            //no cover
            if(st>r||en<l)
                return new QN(-1,0);
            //full cover
            if(l<=st&&en<=r){
                if(su+pmin()<=v)
                    return query2(v,su);
                return new QN(-1,su+sum());
            }
            lazyPropagate();

            QN q1=left.query(l,r,v,su);
            if(q1.index!=-1)
                return q1;
            q1=right.query(l,r,v,q1.sum);
            return q1;
        }
        QN query2(long v,long su){
            if(st==en)
                return new QN(st,su+sum());
            lazyPropagate();
            if(left.pmin()+su<=v)
                return left.query2(v,su);
            else
                return right.query2(v,su+left.sum());

        }

    }
    static class Scanner
    {
        BufferedReader br;
        StringTokenizer tk=new StringTokenizer("");
        public Scanner(InputStream is)
        {
            br=new BufferedReader(new InputStreamReader(is));
        }
        public int nextInt() throws IOException
        {
            if(tk.hasMoreTokens())
                return Integer.parseInt(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextInt();
        }
        public long nextLong() throws IOException
        {
            if(tk.hasMoreTokens())
                return Long.parseLong(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextLong();
        }
        public String next() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return next();
        }
        public String nextLine() throws IOException
        {
            tk=new StringTokenizer("");
            return br.readLine();
        }
        public double nextDouble() throws IOException
        {
            if(tk.hasMoreTokens())
                return Double.parseDouble(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextDouble();
        }
        public char nextChar() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken().charAt(0));
            tk=new StringTokenizer(br.readLine());
            return nextChar();
        }
        public int[] nextIntArray(int n) throws IOException
        {
            int a[]=new int[n];
            for(int i=0;i<n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArray(int n) throws IOException
        {
            long a[]=new long[n];
            for(int i=0;i<n;i++)
                a[i]=nextLong();
            return a;
        }
        public int[] nextIntArrayOneBased(int n) throws IOException
        {
            int a[]=new int[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArrayOneBased(int n) throws IOException
        {
            long a[]=new long[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextLong();
            return a;
        }

    }

    public static void main(String args[]) throws IOException
    {
        Scanner in=new Scanner(System.in);
        PrintWriter out=new PrintWriter(System.out);
        SegmentTree st=new SegmentTree(1,1000000000,0);
        int q=in.nextInt();
        TreeMap<Integer,Integer> mp=new TreeMap<>();
        mp.put(0,0);
        mp.put(1000000001,0);
        while(q--!=0){
            int tp=in.nextInt();
            switch(tp){
                case 1:
                    int tm=in.nextInt();
                    int vl=in.nextInt();
                    int nxt=mp.higherKey(tm)-1;
                    st.update(tm, nxt, vl);
                    mp.put(tm,vl);
                    break;
                case 2:
                    int tc=in.nextInt();
                    int vp=mp.lowerEntry(tc).getValue();
                    int net=mp.higherKey(tc)-1;
                    st.update(tc, net, vp);
                    mp.remove(tc);
                    break;
                case 3:
                    int l=in.nextInt();
                    int lc=l;
                    l=mp.ceilingKey(l);
                    int r=in.nextInt();
                    int v=in.nextInt();
                    if(v==0){
                        out.println(lc);
                        continue;
                    }
                    if(l>=r){
                        out.println(-1);
                        continue;
                    }
                    QN aa=st.query(l, r-1, -v, 0);
                    if(aa.index==-1)
                        out.println(-1);
                    else{
                        int spd=mp.floorEntry(aa.index).getValue();
                        double remv=-(v+(aa.sum-spd));
                        double anss=aa.index;
                        anss+=remv/spd;
                        out.println(anss);

                    }

            }

        }
        out.close();
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.util.TreeMap;
public class E1113
{
    static class QN{
        int index;
        long sum;
        QN(int in,long an){
            index=in;
            sum=an;
        }
    }
    static class SegmentTree{
        long sum,pmin,lazy;
        int st,en;
        boolean rem;
        SegmentTree left,right;
        SegmentTree(int _st,int _en,long _v){
            st=_st;
            en=_en;
            lazy=_v;
            rem=true;
            sum=(en-st+1)*lazy;
            pmin=Math.min(lazy,sum);
        }
        long pmin(){
            return rem?(Math.min(lazy,(en-st+1)*lazy)):(pmin);
        }
        long sum(){
            return rem?((en-st+1)*lazy):(sum);
        }
        void update(int l,int r,long v){
            //completely outside
            if(l>en||r<st)
                return;
            //completely inside
            if(l<=st&&r>=en){
                //update lazy;
                lazy=v;
                rem=true;
                return;
            }
            //partial cover
            lazyPropagate();
            left.update(l, r, v);
            right.update(l, r, v);
            sum=left.sum()+right.sum();
            pmin=Math.min(left.pmin(),left.sum()+right.pmin());
            return;
        }
        void lazyPropagate(){
            if(left==null){
                int mid=(st+en)/2;
                left=new SegmentTree(st,mid,lazy);
                right=new SegmentTree(mid+1,en,lazy);
            }else if(rem){
                left.lazy=lazy;
                right.lazy=lazy;
                left.rem=true;
                right.rem=true;
            }
            if(rem){
                sum=left.sum()+right.sum();
                pmin=Math.min(left.pmin(),left.sum()+right.pmin());
            }
            rem=false;
        }
        /**returns least index which has value <= given value**/
        QN query(int l,int r,long v,long su){
            //no cover
            if(st>r||en<l)
                return new QN(-1,0);
            //full cover
            if(l<=st&&en<=r){
                if(su+pmin()<=v)
                    return query2(v,su);
                return new QN(-1,su+sum());
            }
            lazyPropagate();

            QN q1=left.query(l,r,v,su);
            if(q1.index!=-1)
                return q1;
            q1=right.query(l,r,v,q1.sum);
            return q1;
        }
        QN query2(long v,long su){
            if(st==en)
                return new QN(st,su+sum());
            lazyPropagate();
            if(left.pmin()+su<=v)
                return left.query2(v,su);
            else
                return right.query2(v,su+left.sum());

        }

    }
    static class Scanner
    {
        BufferedReader br;
        StringTokenizer tk=new StringTokenizer("");
        public Scanner(InputStream is)
        {
            br=new BufferedReader(new InputStreamReader(is));
        }
        public int nextInt() throws IOException
        {
            if(tk.hasMoreTokens())
                return Integer.parseInt(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextInt();
        }
        public long nextLong() throws IOException
        {
            if(tk.hasMoreTokens())
                return Long.parseLong(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextLong();
        }
        public String next() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return next();
        }
        public String nextLine() throws IOException
        {
            tk=new StringTokenizer("");
            return br.readLine();
        }
        public double nextDouble() throws IOException
        {
            if(tk.hasMoreTokens())
                return Double.parseDouble(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextDouble();
        }
        public char nextChar() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken().charAt(0));
            tk=new StringTokenizer(br.readLine());
            return nextChar();
        }
        public int[] nextIntArray(int n) throws IOException
        {
            int a[]=new int[n];
            for(int i=0;i<n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArray(int n) throws IOException
        {
            long a[]=new long[n];
            for(int i=0;i<n;i++)
                a[i]=nextLong();
            return a;
        }
        public int[] nextIntArrayOneBased(int n) throws IOException
        {
            int a[]=new int[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArrayOneBased(int n) throws IOException
        {
            long a[]=new long[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextLong();
            return a;
        }

    }

    public static void main(String args[]) throws IOException
    {
        Scanner in=new Scanner(System.in);
        PrintWriter out=new PrintWriter(System.out);
        SegmentTree st=new SegmentTree(1,1000000000,0);
        int q=in.nextInt();
        TreeMap<Integer,Integer> mp=new TreeMap<>();
        mp.put(0,0);
        mp.put(1000000001,0);
        while(q--!=0){
            int tp=in.nextInt();
            switch(tp){
                case 1:
                    int tm=in.nextInt();
                    int vl=in.nextInt();
                    int nxt=mp.higherKey(tm)-1;
                    st.update(tm, nxt, vl);
                    mp.put(tm,vl);
                    break;
                case 2:
                    int tc=in.nextInt();
                    int vp=mp.lowerEntry(tc).getValue();
                    int net=mp.higherKey(tc)-1;
                    st.update(tc, net, vp);
                    mp.remove(tc);
                    break;
                case 3:
                    int l=in.nextInt();
                    int lc=l;
                    l=mp.ceilingKey(l);
                    int r=in.nextInt();
                    int v=in.nextInt();
                    if(v==0){
                        out.println(lc);
                        continue;
                    }
                    if(l>=r){
                        out.println(-1);
                        continue;
                    }
                    QN aa=st.query(l, r-1, -v, 0);
                    if(aa.index==-1)
                        out.println(-1);
                    else{
                        int spd=mp.floorEntry(aa.index).getValue();
                        double remv=-(v+(aa.sum-spd));
                        double anss=aa.index;
                        anss+=remv/spd;
                        out.println(anss);

                    }

            }

        }
        out.close();
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.util.TreeMap;
public class E1113
{
    static class QN{
        int index;
        long sum;
        QN(int in,long an){
            index=in;
            sum=an;
        }
    }
    static class SegmentTree{
        long sum,pmin,lazy;
        int st,en;
        boolean rem;
        SegmentTree left,right;
        SegmentTree(int _st,int _en,long _v){
            st=_st;
            en=_en;
            lazy=_v;
            rem=true;
            sum=(en-st+1)*lazy;
            pmin=Math.min(lazy,sum);
        }
        long pmin(){
            return rem?(Math.min(lazy,(en-st+1)*lazy)):(pmin);
        }
        long sum(){
            return rem?((en-st+1)*lazy):(sum);
        }
        void update(int l,int r,long v){
            //completely outside
            if(l>en||r<st)
                return;
            //completely inside
            if(l<=st&&r>=en){
                //update lazy;
                lazy=v;
                rem=true;
                return;
            }
            //partial cover
            lazyPropagate();
            left.update(l, r, v);
            right.update(l, r, v);
            sum=left.sum()+right.sum();
            pmin=Math.min(left.pmin(),left.sum()+right.pmin());
            return;
        }
        void lazyPropagate(){
            if(left==null){
                int mid=(st+en)/2;
                left=new SegmentTree(st,mid,lazy);
                right=new SegmentTree(mid+1,en,lazy);
            }else if(rem){
                left.lazy=lazy;
                right.lazy=lazy;
                left.rem=true;
                right.rem=true;
            }
            rem=false;
        }
        /**returns least index which has value <= given value**/
        QN query(int l,int r,int v,long su){
            //no cover
            if(st>r||en<l)
                return new QN(-1,0);
            //full cover
            if(l<=st&&en<=r){
                if(su+pmin()<=v)
                    return query2(v,su);
                return new QN(-1,sum());
            }
            lazyPropagate();
            sum=left.sum()+right.sum();
            pmin=Math.min(left.pmin(),left.sum()+right.pmin());
            QN q1=left.query(l,r,v,su);
            if(q1.index!=-1)
                return q1;
            q1=right.query(l,r,v,su+q1.sum);
            return q1;
        }
        QN query2(long v,long su){
            if(st==en)
                return new QN(st,su+sum());
            lazyPropagate();
            sum=left.sum()+right.sum();
            pmin=Math.min(left.pmin(),left.sum()+right.pmin());
            if(left.pmin()+su<=v)
                return left.query2(v,su);
            else
                return right.query2(v,su+left.sum());

        }

    }
    static class Scanner
    {
        BufferedReader br;
        StringTokenizer tk=new StringTokenizer("");
        public Scanner(InputStream is)
        {
            br=new BufferedReader(new InputStreamReader(is));
        }
        public int nextInt() throws IOException
        {
            if(tk.hasMoreTokens())
                return Integer.parseInt(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextInt();
        }
        public long nextLong() throws IOException
        {
            if(tk.hasMoreTokens())
                return Long.parseLong(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextLong();
        }
        public String next() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return next();
        }
        public String nextLine() throws IOException
        {
            tk=new StringTokenizer("");
            return br.readLine();
        }
        public double nextDouble() throws IOException
        {
            if(tk.hasMoreTokens())
                return Double.parseDouble(tk.nextToken());
            tk=new StringTokenizer(br.readLine());
            return nextDouble();
        }
        public char nextChar() throws IOException
        {
            if(tk.hasMoreTokens())
                return (tk.nextToken().charAt(0));
            tk=new StringTokenizer(br.readLine());
            return nextChar();
        }
        public int[] nextIntArray(int n) throws IOException
        {
            int a[]=new int[n];
            for(int i=0;i<n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArray(int n) throws IOException
        {
            long a[]=new long[n];
            for(int i=0;i<n;i++)
                a[i]=nextLong();
            return a;
        }
        public int[] nextIntArrayOneBased(int n) throws IOException
        {
            int a[]=new int[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextInt();
            return a;
        }
        public long[] nextLongArrayOneBased(int n) throws IOException
        {
            long a[]=new long[n+1];
            for(int i=1;i<=n;i++)
                a[i]=nextLong();
            return a;
        }

    }

    public static void main(String args[]) throws IOException
    {
        Scanner in=new Scanner(System.in);
        PrintWriter out=new PrintWriter(System.out);
        SegmentTree st=new SegmentTree(1,1000000000,0);
        int q=in.nextInt();
        TreeMap<Integer,Integer> mp=new TreeMap<>();
        mp.put(0,0);
        mp.put(1000000001,0);
        while(q--!=0){
            int tp=in.nextInt();
            switch(tp){
                case 1:
                    int tm=in.nextInt();
                    int vl=in.nextInt();
                    int nxt=mp.higherKey(tm)-1;
                    st.update(tm, nxt, vl);
                    mp.put(tm,vl);
                    break;
                case 2:
                    int tc=in.nextInt();
                    int vp=mp.lowerEntry(tc).getValue();
                    int net=mp.higherKey(tc)-1;
                    st.update(tc, net, vp);
                    mp.remove(tc);
                    break;
                case 3:
                    int l=in.nextInt();
                    int r=in.nextInt();
                    int v=in.nextInt();
                    if(v==0){
                        out.println(l);
                        continue;
                    }
                    if(l==r){
                        out.println(-1);
                        continue;
                    }
                    QN aa=st.query(l, r-1, -v, 0);
                    if(aa.index==-1)
                        out.println(-1);
                    else{
                        int spd=mp.floorEntry(aa.index).getValue();
                        double remv=-(v+(aa.sum-spd));
                        double anss=aa.index;
                        anss+=remv/spd;
                        out.println(anss);

                    }

            }

        }
        out.close();
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;

public class E {
	static long mod = 1000000009;
	static long[][] ways = new long[1001][1001];
	static int k;

	public static long getTotal(String x) {
		long ans = 0;
		for (int i = 0; i < x.length(); i++)
			ans = (10 * ans + x.charAt(i) - '0') % mod;
		return ans;
	}

	public static long get(String x, int index, int cantPut47) {
		if (index == x.length())
			return 1;
		int maxDigit = x.charAt(index) - '0';
		long ans = 0;
		for (int i = 0; i <= maxDigit; i++) {
			if ((i == 4 || i == 7) && cantPut47 > 0)
				continue;
			if (i == 4 || i == 7)
				if (i < maxDigit)
					ans = (ans + ways[x.length() - index - 1][k]) % mod;
				else
					ans = (ans + get(x, index + 1, k)) % mod;
			else if (i < maxDigit)
				ans = (ans + ways[x.length() - index - 1][Math.max(
						cantPut47 - 1, 0)]) % mod;
			else
				ans = (ans + get(x, index + 1, Math.max(cantPut47 - 1, 0)))
						% mod;
		}
		return ans;
	}

	public static void main(String[] args) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String[] S = in.readLine().split(" ");
		int t = Integer.parseInt(S[0]);
		k = Integer.parseInt(S[1]);
		for (int i = 0; i < 1001; i++)
			ways[0][i] = 1;
		for (int i = 1; i < 1001; i++)
			for (int j = 0; j < 1001; j++)
				if (j == 0)
					ways[i][j] = (8 * ways[i - 1][0] + 2 * ways[i - 1][k])
							% mod;
				else
					ways[i][j] = (8 * ways[i - 1][j - 1]) % mod;
		for (int i = 0; i < t; i++) {
			S = in.readLine().split(" ");
			String left = "" + (new BigInteger(S[0]).subtract(BigInteger.ONE));
			String right = S[1];
			long tot = (getTotal(right) - getTotal(left) + mod) % mod;
			long bad = (get(right, 0, 0) - get(left, 0, 0) + mod) % mod;
			long ans = (tot - bad + mod) % mod;
			System.out.println(ans);
		}
	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileNotFoundException;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;

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

	static class F {
		private Long[][] lastX = new Long[2010][2010];
		private long mod = 998244353;
		private long p = 0;
		private long[] pPow = new long[2010];
		private long[] qPow = new long[2010];
		private long[] strong = new long[2010];
		private Long[] dp = new Long[2010];

		public void solve(int testNumber, InputReader in, PrintWriter out) {
			int n = in.nextInt();
			int a = in.nextInt(), b = in.nextInt();
			p = MathUtils.powMod(b, mod - 2, mod) * a % mod;
			pPow[0] = 1;
			qPow[0] = 1;
			for (int i = 1; i < 2010; ++i) {
				pPow[i] = pPow[i - 1] * p % mod;
				qPow[i] = qPow[i - 1] * (1 - p + mod) % mod;
			}
			strong[1] = 1;
			for (int i = 2; i <= n; ++i) {
				long ans = 0;
				for (int j = 1; j < i; ++j) {
					ans += strong[j] * computeLastX(i, j) % mod;
					if (ans >= mod) ans -= mod;
				}
				strong[i] = 1 - ans;
				if (strong[i] < 0) strong[i] += mod;
			}
			long ans = dp(n);
			out.println(ans);
		}

		private long computeLastX(int n, int i) {
			if (lastX[n][i] != null) return lastX[n][i];
			if (n == i || i == 0) return lastX[n][i] = 1L;
			long ans = qPow[i] * computeLastX(n - 1, i) % mod + pPow[n - i] * computeLastX(n - 1, i - 1) % mod;
			return lastX[n][i] = ans % mod;
		}

		private long dp(int n) {
			if (dp[n] != null) return dp[n];
			if (n < 2) return dp[n] = 0L;
			if (n < 3) return dp[n] = 1L;
			long ans = strong[n] * (n * (n - 1) / 2) % mod;
			for (int x = 1; x < n; ++x) {
				long tmp = computeLastX(n, x) * strong[x] % mod;
				tmp *= (x * (x - 1) / 2 + x * (n - x) + dp(n - x) + dp(x)) % mod;
				ans += tmp % mod;
			}
			ans %= mod;
			ans *= MathUtils.powMod(1 + mod - strong[n], mod - 2, mod);
			return dp[n] = ans % mod;
		}

	}

	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public InputReader(InputStream inputStream) {
			reader = new BufferedReader(new InputStreamReader(inputStream));
			tokenizer = null;
		}

		public InputReader(String inputFile) throws FileNotFoundException {
			reader = new BufferedReader(new FileReader(inputFile));
			tokenizer = null;
		}

		public String nextLine() {
			String curr = "";
			try {
				curr = reader.readLine();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			return curr;
		}

		public String nextString() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(nextLine());
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

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

	}

	static class MathUtils {
		public static long powMod(long a, long b, long m) {
			long ans = 1;
			while (b > 0) {
				if (b % 2 == 1) ans = ans * a % m;
				b >>= 1;
				a = a * a % m;
			}
			return ans % m;
		}

	}
}


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

public class Codeforces913F {
	public static void main(String[] args) throws IOException {
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		int a = input.nextInt();
		int b = input.nextInt();
		input.close();
		final int mod = 998244353;

		int frac = multiply(a, inverse(b, mod), mod);
		int reverse = (mod+1-frac)%mod;

		int[] fracpower = new int[n+1];
		int[] reversepower = new int[n+1];
		fracpower[0] = 1;
		reversepower[0] = 1;
		for (int i = 1; i <= n; i++) {
			fracpower[i] = multiply(fracpower[i-1], frac, mod);
			reversepower[i] = multiply(reversepower[i-1], reverse, mod);
		}

		int[][] dp1 = new int[n+1][n+1];
		dp1[2][1] = 1;
		for (int i = 3; i <= n; i++) {
			for (int j = 1; j < i; j++) {
				if (j == 1) {
					dp1[i][j] = fracpower[i-1];
				}
				else {
					dp1[i][j] = multiply(dp1[i-1][j-1], fracpower[i-j], mod);
				}
				if (j == i-1) {
					dp1[i][j] += reversepower[i-1];
					dp1[i][j] %= mod;
				}
				else {
					dp1[i][j] += multiply(dp1[i-1][j], reversepower[j], mod);
					dp1[i][j] %= mod;
				}
			}
		}

		int[][] dp2 = new int[n+1][n+1];
		dp2[1][1] = 1;
		dp2[2][1] = 1;
		dp2[2][2] = 0;
		for (int i = 3; i <= n; i++) {
			int val = 0;
			for (int j = 1; j < i; j++) {
				dp2[i][j] = multiply(dp2[j][j], dp1[i][j], mod);
				val += dp2[i][j];
				val %= mod;
			}
			dp2[i][i] = (mod+1-val)%mod;
		}

		for (int i = 2; i <= n; i++) {
			for (int j = 1; j <= i; j++) {
				System.out.print(dp2[i][j] + " ");
			}
			System.out.println();
		}

		int[] EV = new int[n+1];
		EV[1] = 0;
		EV[2] = 1;
		for (int i = 3; i <= n; i++) {
			int val = 0;
			for (int j = 1; j < i; j++) {
				int r = j*(i-j) + (j*(j-1))/2 + EV[i-j] + EV[j];
				r %= mod;
				val += multiply(dp2[i][j], r, mod);
				val %= mod;
			}
			val += multiply((i*(i-1))/2, dp2[i][i], mod);
			val %= mod;

			int s = (mod+1-dp2[i][i])%mod;
			EV[i] = multiply(val, inverse(s, mod), mod);
		}

		System.out.println(EV[n]);
	}

	public static int multiply(int a, int b, int mod) {
		long x = (long)a*(long)b;
		return (int) (x%mod);
	}

	public static int inverse (int a, int n) {
		int m = n;
		int r1 = 1;
		int r2 = 0;
		int r3 = 0;
		int r4 = 1;
		while ((a > 0) && (n > 0)) {
			if (n >= a) {
				r3 -= r1*(n/a);
				r4 -= r2*(n/a);
				n = n%a;
			}
			else {
				int tmp = a;
				a = n;
				n = tmp;
				tmp = r1;
				r1 = r3;
				r3 = tmp;
				tmp = r2;
				r2 = r4;
				r4 = tmp;
			}
		}
		if (a == 0) {
			if (r3 >= 0)
				return (r3%m);
			else
				return (m+(r3%m));
		}
		else {
			if (r1 >= 0)
				return (r1%m);
			else
				return (m+(r1%m));
		}

	}
}


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.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 < 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.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

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

    long INF = (long) 1e18;

    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 < 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.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.Comparator;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.List;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Egor Kulikov (egor@egork.net)
 */
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);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
	static final long MOD = 1000000007;

	long[][][] result;
	long[][][] resultSmall;
	long[][] c = IntegerUtils.generateBinomialCoefficients(13);

    public void solve(int testNumber, InputReader in, OutputWriter out) {
		int size = in.readInt();
		int count = in.readInt();
		result = new long[size + 1][count + 1][16];
		resultSmall = new long[size + 1][count + 1][16];
		ArrayUtils.fill(result, -1);
		ArrayUtils.fill(resultSmall, -1);
		long answer = calculate(size, count, 0);
		answer *= IntegerUtils.factorial(count, MOD);
		answer %= MOD;
		out.printLine(answer);
    }

	private long calculate(int size, int count, int mask) {
		if (count < 0)
			return 0;
		if (result[size][count][mask] != -1)
			return result[size][count][mask];
		long current = 0;
		if (mask == 0)
			current += 2 * calculate(0, count - 2, 15);
		for (int i = 0; i < 4; i++) {
			int j = (i + 1) & 3;
			if ((mask >> i & 1) != 0 || (mask >> j & 1) != 0)
				continue;
			int remaining = 15 - mask - (1 << i) - (1 << j);
			for (int k = remaining; ; k = (k - 1) & remaining) {
				current += calculateSmall(size, count - 1 - Integer.bitCount(k), mask + (1 << i) + (1 << j) + k);
				if (k == 0)
					break;
			}
		}
		int remaining = 15 - mask;
		for (int k = remaining; ; k = (k - 1) & remaining) {
			current += calculateSmall(size, count - Integer.bitCount(k), mask + k);
			if (k == 0)
				break;
		}
		return result[size][count][mask] = current % MOD;
	}

	private long calculateSmall(int size, int count, int mask) {
		if (count < 0)
			return 0;
		if (resultSmall[size][count][mask] != -1)
			return resultSmall[size][count][mask];
		if (size == 0)
			return resultSmall[size][count][mask] = count == 0 ? 1 : 0;
		int max = 3 * Integer.bitCount(15 - mask);
		int pairCount = 0;
		for (int i = 0; i < 4; i++) {
			int j = (i + 1) & 3;
			if ((mask >> i & 1) == 0 && ((mask >> j & 1) == 0))
				pairCount++;
		}
		long current = 0;
		for (int j = 0; j <= pairCount; j++) {
			for (int i = 0; i <= max - 2 * j; i++)
				current += calculate(size - 1, count - i - j, mask) * c[max - 2 * j][i] * c[pairCount][j];
		}
		return resultSmall[size][count][mask] = current % MOD;
	}
}

class IntegerUtils {

    public static long[][] generateBinomialCoefficients(int n) {
		long[][] result = new long[n + 1][n + 1];
		for (int i = 0; i <= n; i++) {
			result[i][0] = 1;
			for (int j = 1; j <= i; j++)
				result[i][j] = result[i - 1][j - 1] + result[i - 1][j];
		}
		return result;
	}

	public static long factorial(int n, long mod) {
		long result = 1;
		for (int i = 2; i <= n; i++)
			result = result * i % mod;
		return result % mod;
	}

	}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private 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 {
		public boolean isSpaceChar(int ch);
	}
}

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(Object...objects) {
		print(objects);
		writer.println();
	}

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

	}

class ArrayUtils {

	public static void fill(long[][] array, long value) {
		for (long[] row : array)
			Arrays.fill(row, value);
	}

	public static void fill(long[][][] array, long value) {
		for (long[][] row : array)
			fill(row, value);
	}

	}


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

// you can compare with output.txt and expected out
public class RoundEdu132F {
	MyPrintWriter out;
	MyScanner in;

//	final static long FIXED_RANDOM;
//	static {
//		FIXED_RANDOM = System.currentTimeMillis();
//	}
	final static String IMPOSSIBLE = "IMPOSSIBLE";
	final static String POSSIBLE = "POSSIBLE";
	final static String YES = "YES";
	final static String NO = "NO";

    private void initIO(boolean isFileIO) {
        if (System.getProperty("ONLINE_JUDGE") == null && isFileIO) {
        	try{
	            in = new MyScanner(new FileInputStream("input.txt"));
	            out = new MyPrintWriter(new FileOutputStream("output.txt"));
        	}
        	catch(FileNotFoundException e){
        		e.printStackTrace();
        	}
        }
        else{
    		in = new MyScanner(System.in);
    	    out = new MyPrintWriter(new BufferedOutputStream(System.out));
        }
    }

	public static void main(String[] args){
//		Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in)));

		RoundEdu132F sol = new RoundEdu132F();
		sol.run();
    }

	private void run() {
		boolean isDebug = false;
		boolean isFileIO = true;
		boolean hasMultipleTests = true;

		initIO(isFileIO);

		int t = hasMultipleTests? in.nextInt() : 1;

	    for (int i = 1; i <= t; ++i) {
	    	if(isDebug){
		    	out.printf("Test %d\n", i);
	    	}

	    	getInput();

	    	ans = solve();

	    	printOutput();
	    }

	    in.close();
	    out.close();
	}

	int n, k, f;
	void getInput() {
		n = in.nextInt();
		k = in.nextInt();
		f = in.nextInt();
	}

	void printOutput() {
		out.printlnAns(ans);
	}

	static final long MOD = 998244353;
	int ans;
	int solve(){
		long ans = 0;

		// for each binary string s,
		// consider binary strings t of length n, where s is a prefix of t
		// we can have <= c_s among t

		// it's a full binary tree
		// where each vertex contains # of records in its subtree
		// and all records are at depth n

		// from each leaf, go up again, update each vertex to min(val, val(child1) + val(child2))
		// then the val(root) must be exactly f
		// where root is null string

		// the problem in this counting is we would have to use inclusion-exclusion due to duplicate cases
		// so we choose vertices representing disjoint subtrees
		// whose union can represent the whole tree
		// and whose sum is exactly f

		// for vertices under the subtrees, we can freely choose val
		// so that sum of siblings in each subtree >= val of root of subtree
		// for vertices above the subtrees, we can freely choose val between sum and k

		// so another approach:
		// for each vertex v of depth h
		// find # of ways to make sum exactly x
		// case 1: val(v) = x
		// add up ways(l, y)*ways(r, z) where y+z >= x
		// case 2: val(v) >= x+1
		// add up ways(l, y)*ways(r, z) where y+z = x

		// takes up space: n*k*2 <= 30k = 6*10^6 < 100MB
		// time: O(nk), should fit in 6s

		// 2 1 1
		// case 1: c_0 = 1, c_1 = 0
		// 00 01 10 11
		// 1  0  0/1 0/1
		// 0  1  0/1 0/1
		// 1  1  0/1 0/1
		// -> 12

		// case 2: c_0 = 0, c_1 = 1
		// -> 12

		// case 3: c_0 = 1, c_1 = 1
		// 1 0 0 0
		// 0 1 0 0
		// 1 1 0 0
		// 0 0 1 0
		// 0 0 0 1
		// 0 0 1 1
		// -> 6

		// subtree_0 = 1 -> 3
		// c_0 = 1 -> 1 0, 0 1, 1 1

		// subtree_0 = 0 -> 5
		// c_0 = 0 -> 0/1, 0/1 -> 4
		// c_0 = 1 -> 0, 0 -> 1
		// 3*5 + 3*5 = 30

		// subtree_l = 0 -> 1
		// subtree_l = 1 -> 1

		ArrayList<Long> ways = new ArrayList<>(f+2);
		ArrayList<Long> suffix = new ArrayList<>(f+2);
		for(int i=0; i<=f+1; i++)
			ways.add(0L);
		for(int i=0; i<=f+1; i++)
			suffix.add(0L);

		for(int i=0; i<=k && i<=f; i++) {
			ways.set(i, 1L);
		}
		ways.set(f+1, Math.max(0, (long) (k-f)));

		for(int i=0; i<n; i++) {
			var mult = multiplyPolynomial(ways, ways);
			{
				long val = 0;
				for(int j=mult.size()-1; j>=f+1; j--)
					val += mult.get(j);
				val %= MOD;
				suffix.set(f+1, val);
			}
			for(int j=f; j>=0; j--){
				long val = suffix.get(j+1) + mult.get(j);
				val = val>=MOD? val-MOD: val;
				suffix.set(j, val);
			}
			if(i < n-1) {
				for(int j=0; j <= k && j<=f; j++) {
					long val = suffix.get(j); // c_curr = j
					val += mult.get(j)*(k-j); // j+1 ~ k
					val %= MOD;
					ways.set(j, val);
				}
				{
					long val = suffix.get(f+1)*Math.max(0, k-f);
					val %= MOD;
					ways.set(f+1, val);
				}
			}
			else {
				ans = mult.get(f);
			}
		}

		return (int)ans;
	}

	static long pow(int a, int k, long p) {
		long m = k;
		long ans = 1;

		// curr = k^(2^i)
		long curr = a;

		// k^(2x+1) = (k^x)^2 * k
		while(m > 0) {
			if( (m&1) == 1 ) {
				ans *= curr;
				ans %= p;
			}
			m >>= 1;
			curr *= curr;
			curr %= p;
		}
		return ans;
	}

	// computes a^(p-2)
	static long inverse(int a, long p) {
		return pow(a, (int)(p-2), p);
	}

	// static final long MOD = 998_244_353; // = 1 + 7*17*2^23
	// primitive root is 3, i.e., the order of 3 is MOD-1
	// we have to find the 1<<23-th root
	static final int ROOT = (int) pow(3, 7*17, MOD);
	static final int ROOT_INV = (int) pow(ROOT, (int)MOD - 2, MOD);
	static final int ORDER = 1 << 23;

	static void fft(ArrayList<Long> a, boolean isInvertedFFT) {
	    int n = a.size();

	    for (int i = 1, j = 0; i < n; i++) {
	        int bit = n >> 1;
	        for (; (j & bit) > 0; bit >>= 1)
	            j ^= bit;
	        j ^= bit;

	        if (i < j) {
	        	Collections.swap(a, i, j);
	        }
	    }

	    for (int len = 2; len <= n; len <<= 1) {
	        long wlen = isInvertedFFT ? ROOT_INV : ROOT;
	        for (int i = len; i < ORDER; i <<= 1)
	            wlen = wlen * wlen % MOD;

	        for (int i = 0; i < n; i += len) {
	        	long w = 1;
	            for (int j = 0; j < len / 2; j++) {
	                long u = a.get(i+j);
	                long v = a.get(i+j+len/2) * w % MOD;
	                a.set(i+j,  u + v < MOD ? u + v : u + v - MOD);
	                a.set(i+j+len/2, u - v >= 0 ? u - v : u - v + MOD);
	                w = w * wlen % MOD;
	            }
	        }
	    }

	    if (isInvertedFFT) {
	        int inv = (int) inverse(n, MOD);
	        //a = (ArrayList<Long>) a.stream().map(x -> x*inv%MOD).collect(Collectors.toList());
	        var iter = a.listIterator();
	        while(iter.hasNext()) {
	        	iter.set(iter.next()*inv%MOD);
	        }
	    }
	}

	static ArrayList<Long> multiplyPolynomial(ArrayList<Long> a, ArrayList<Long> b) {
		ArrayList<Long> fa = (ArrayList<Long>) a.clone();
		ArrayList<Long> fb = (ArrayList<Long>) b.clone();
	    int n = 1;
	    while (n < a.size() + b.size())
	        n <<= 1;
	    for(int i=fa.size(); i<n; i++)
	    	fa.add(0l);
	    for(int i=fb.size(); i<n; i++)
	    	fb.add(0l);

	    fft(fa, false);
	    fft(fb, false);
	    for (int i = 0; i < n; i++)
	        fa.set(i, fa.get(i)*fb.get(i) % MOD);
	    fft(fa, true);

	    ArrayList<Long> result = new ArrayList<>(n);
	    for (int i = 0; i < n; i++)
	    	result.add(fa.get(i));
	    return result;
	}

	public static class MyScanner {
		BufferedReader br;
		StringTokenizer st;

		// 32768?
		public MyScanner(InputStream is, int bufferSize) {
			br = new BufferedReader(new InputStreamReader(is), bufferSize);
		}

		public MyScanner(InputStream is) {
			br = new BufferedReader(new InputStreamReader(is));
			// br = new BufferedReader(new InputStreamReader(System.in));
			// br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
		}

		public void close() {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

		String next() {
			while (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

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

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

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

		String nextLine(){
			String str = "";
			try {
				str = br.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return str;
		}

		int[][] nextTreeEdges(int n, int offset){
			int[][] e = new int[n-1][2];
			for(int i=0; i<n-1; i++){
				e[i][0] = nextInt()+offset;
				e[i][1] = nextInt()+offset;
			}
			return e;
		}

		int[][] nextMatrix(int n, int m) {
			return nextMatrix(n, m, 0);
		}

		int[][] nextMatrix(int n, int m, int offset) {
			int[][] mat = new int[n][m];
			for(int i=0; i<n; i++) {
				for(int j=0; j<m; j++) {
					mat[i][j] = nextInt()+offset;
				}
			}
			return mat;
		}

		int[][] nextPairs(int n){
			return nextPairs(n, 0);
		}

		int[][] nextPairs(int n, int offset) {
			int[][] xy = new int[2][n];
			for(int i=0; i<n; i++) {
				xy[0][i] = nextInt() + offset;
				xy[1][i] = nextInt() + offset;
			}
			return xy;
		}

		int[][] nextGraphEdges(){
			return nextGraphEdges(0);
		}

		int[][] nextGraphEdges(int offset) {
			int m = nextInt();
			int[][] e = new int[m][2];
			for(int i=0; i<m; i++){
				e[i][0] = nextInt()+offset;
				e[i][1] = nextInt()+offset;
			}
			return e;
		}

		int[] nextIntArray(int len) {
			return nextIntArray(len, 0);
		}
		int[] nextIntArray(int len, int offset){
	    	int[] a = new int[len];
			for(int j=0; j<len; j++)
	    		a[j] = nextInt()+offset;
	    	return a;
		}

		long[] nextLongArray(int len) {
			return nextLongArray(len, 0);
		}
		long[] nextLongArray(int len, int offset){
	    	long[] a = new long[len];
			for(int j=0; j<len; j++)
	    		a[j] = nextLong()+offset;
	    	return a;
		}
	}

	public static class MyPrintWriter extends PrintWriter{
		public MyPrintWriter(OutputStream os) {
			super(os);
		}

		public void printlnAns(long ans) {
			println(ans);
		}

		public void printlnAns(int ans) {
			println(ans);
		}

		public void printlnAns(boolean ans) {
			if(ans)
				println(YES);
			else
				println(NO);
		}

		public void printAns(long[] arr){
			if(arr != null && arr.length > 0){
				print(arr[0]);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]);
				}
			}
		}
		public void printlnAns(long[] arr){
			printAns(arr);
			println();
		}

		public void printAns(int[] arr){
			if(arr != null && arr.length > 0){
				print(arr[0]);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]);
				}
			}
		}
		public void printlnAns(int[] arr){
			printAns(arr);
			println();
		}

		public <T> void printAns(ArrayList<T> arr){
			if(arr != null && arr.size() > 0){
				print(arr.get(0));
				for(int i=1; i<arr.size(); i++){
					print(" ");
					print(arr.get(i));
				}
			}
		}
		public <T> void printlnAns(ArrayList<T> arr){
			printAns(arr);
			println();
		}

		public void printAns(int[] arr, int add){
			if(arr != null && arr.length > 0){
				print(arr[0]+add);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]+add);
				}
			}
		}
		public void printlnAns(int[] arr, int add){
			printAns(arr, add);
			println();
		}

		public void printAns(ArrayList<Integer> arr, int add) {
			if(arr != null && arr.size() > 0){
				print(arr.get(0)+add);
				for(int i=1; i<arr.size(); i++){
					print(" ");
					print(arr.get(i)+add);
				}
			}
		}

		public void printlnAns(ArrayList<Integer> arr, int add){
			printAns(arr, add);
			println();
		}

		public void printlnAnsSplit(long[] arr, int split){
			if(arr != null){
				for(int i=0; i<arr.length; i+=split){
					print(arr[i]);
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr[j]);
					}
					println();
				}
			}
		}

		public void printlnAnsSplit(int[] arr, int split){
			if(arr != null){
				for(int i=0; i<arr.length; i+=split){
					print(arr[i]);
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr[j]);
					}
					println();
				}
			}
		}

		public <T> void printlnAnsSplit(ArrayList<T> arr, int split){
			if(arr != null && !arr.isEmpty()){
				for(int i=0; i<arr.size(); i+=split){
					print(arr.get(i));
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr.get(j));
					}
					println();
				}
			}
		}
	}

	static private void permutateAndSort(long[] a) {
		int n = a.length;
		Random R = new Random(System.currentTimeMillis());
		for(int i=0; i<n; i++) {
			int t = R.nextInt(n-i);
			long temp = a[n-1-i];
			a[n-1-i] = a[t];
			a[t] = temp;
		}
		Arrays.sort(a);
	}

	static private void permutateAndSort(int[] a) {
		int n = a.length;
		Random R = new Random(System.currentTimeMillis());
		for(int i=0; i<n; i++) {
			int t = R.nextInt(n-i);
			int temp = a[n-1-i];
			a[n-1-i] = a[t];
			a[t] = temp;
		}
		Arrays.sort(a);
	}

	static private int[][] constructChildren(int n, int[] parent, int parentRoot){
		int[][] childrens = new int[n][];

		int[] numChildren = new int[n];
		for(int i=0; i<parent.length; i++) {
			if(parent[i] != parentRoot)
				numChildren[parent[i]]++;
		}

		for(int i=0; i<n; i++) {
			childrens[i] = new int[numChildren[i]];
		}

		int[] idx = new int[n];
		for(int i=0; i<parent.length; i++) {
			if(parent[i] != parentRoot)
				childrens[parent[i]][idx[parent[i]]++] = i;
		}

		return childrens;
	}

	static private int[][][] constructDirectedNeighborhood(int n, int[][] e){
		int[] inDegree = new int[n];
		int[] outDegree = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			outDegree[u]++;
			inDegree[v]++;
		}

		int[][] inNeighbors = new int[n][];
		int[][] outNeighbors = new int[n][];
		for(int i=0; i<n; i++) {
			inNeighbors[i] = new int[inDegree[i]];
			outNeighbors[i] = new int[outDegree[i]];
		}

		int[] inIdx = new int[n];
		int[] outIdx = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			outNeighbors[u][outIdx[u]++] = v;
			inNeighbors[v][inIdx[v]++] = u;
		}

		return new int[][][] {inNeighbors, outNeighbors};
	}

	static private int[][] constructNeighborhood(int n, int[][] e) {
		int[] degree = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			degree[u]++;
			degree[v]++;
		}

		int[][] neighbors = new int[n][];
		for(int i=0; i<n; i++)
			neighbors[i] = new int[degree[i]];

		int[] idx = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			neighbors[u][idx[u]++] = v;
			neighbors[v][idx[v]++] = u;
		}

		return neighbors;
	}

	static private void drawGraph(int[][] e) {
		makeDotUndirected(e);
		try {
			final Process process = new ProcessBuilder("dot", "-Tpng", "graph.dot")
					.redirectOutput(new File("graph.png"))
					.start();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

	static private void makeDotUndirected(int[][] e) {
		MyPrintWriter out2 = null;
		 try {
			out2 = new MyPrintWriter(new FileOutputStream("graph.dot"));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		out2.println("strict graph {");
		for(int i=0; i<e.length; i++){
			out2.println(e[i][0] + "--" + e[i][1] + ";");
		}
		out2.println("}");
		out2.close();
	}

	static private void makeDotDirected(int[][] e) {
		MyPrintWriter out2 = null;
		 try {
			out2 = new MyPrintWriter(new FileOutputStream("graph.dot"));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		out2.println("strict digraph {");
		for(int i=0; i<e.length; i++){
			out2.println(e[i][0] + "->" + e[i][1] + ";");
		}
		out2.println("}");
		out2.close();
	}

}


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

// you can compare with output.txt and expected out
public class RoundEdu132F {
	MyPrintWriter out;
	MyScanner in;

//	final static long FIXED_RANDOM;
//	static {
//		FIXED_RANDOM = System.currentTimeMillis();
//	}
	final static String IMPOSSIBLE = "IMPOSSIBLE";
	final static String POSSIBLE = "POSSIBLE";
	final static String YES = "YES";
	final static String NO = "NO";

    private void initIO(boolean isFileIO) {
        if (System.getProperty("ONLINE_JUDGE") == null && isFileIO) {
        	try{
	            in = new MyScanner(new FileInputStream("input.txt"));
	            out = new MyPrintWriter(new FileOutputStream("output.txt"));
        	}
        	catch(FileNotFoundException e){
        		e.printStackTrace();
        	}
        }
        else{
    		in = new MyScanner(System.in);
    	    out = new MyPrintWriter(new BufferedOutputStream(System.out));
        }
    }

	public static void main(String[] args){
//		Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in)));

		RoundEdu132F sol = new RoundEdu132F();
		sol.run();
    }

	private void run() {
		boolean isDebug = false;
		boolean isFileIO = true;
		boolean hasMultipleTests = false;

		initIO(isFileIO);

		int t = hasMultipleTests? in.nextInt() : 1;

	    for (int i = 1; i <= t; ++i) {
	    	if(isDebug){
		    	out.printf("Test %d\n", i);
	    	}

	    	getInput();

	    	ans = solve();

	    	printOutput();
	    }

	    in.close();
	    out.close();
	}

	int n, k, f;
	void getInput() {
		n = in.nextInt();
		k = in.nextInt();
		f = in.nextInt();
	}

	void printOutput() {
		out.printlnAns(ans);
	}

	static final long MOD = 998244353;
	int ans;
	int solve(){
		long ans = 0;

		// for each binary string s,
		// consider binary strings t of length n, where s is a prefix of t
		// we can have <= c_s among t

		// it's a full binary tree
		// where each vertex contains # of records in its subtree
		// and all records are at depth n

		// from each leaf, go up again, update each vertex to min(val, val(child1) + val(child2))
		// then the val(root) must be exactly f
		// where root is null string

		// the problem in this counting is we would have to use inclusion-exclusion due to duplicate cases
		// so we choose vertices representing disjoint subtrees
		// whose union can represent the whole tree
		// and whose sum is exactly f

		// for vertices under the subtrees, we can freely choose val
		// so that sum of siblings in each subtree >= val of root of subtree
		// for vertices above the subtrees, we can freely choose val between sum and k

		// so another approach:
		// for each vertex v of depth h
		// find # of ways to make sum exactly x
		// case 1: val(v) = x
		// add up ways(l, y)*ways(r, z) where y+z >= x
		// case 2: val(v) >= x+1
		// add up ways(l, y)*ways(r, z) where y+z = x

		// takes up space: n*k*2 <= 30k = 6*10^6 < 100MB
		// time: O(nk), should fit in 6s

		// 2 1 1
		// case 1: c_0 = 1, c_1 = 0
		// 00 01 10 11
		// 1  0  0/1 0/1
		// 0  1  0/1 0/1
		// 1  1  0/1 0/1
		// -> 12

		// case 2: c_0 = 0, c_1 = 1
		// -> 12

		// case 3: c_0 = 1, c_1 = 1
		// 1 0 0 0
		// 0 1 0 0
		// 1 1 0 0
		// 0 0 1 0
		// 0 0 0 1
		// 0 0 1 1
		// -> 6

		// subtree_0 = 1 -> 3
		// c_0 = 1 -> 1 0, 0 1, 1 1

		// subtree_0 = 0 -> 5
		// c_0 = 0 -> 0/1, 0/1 -> 4
		// c_0 = 1 -> 0, 0 -> 1
		// 3*5 + 3*5 = 30

		// subtree_l = 0 -> 1
		// subtree_l = 1 -> 1

		ArrayList<Long> ways = new ArrayList<>(f+2);
		ArrayList<Long> suffix = new ArrayList<>(f+2);
		for(int i=0; i<=f+1; i++)
			ways.add(0L);
		for(int i=0; i<=f+1; i++)
			suffix.add(0L);

		for(int i=0; i<=k && i<=f; i++) {
			ways.set(i, 1L);
		}
		ways.set(f+1, Math.max(0, (long) (k-f)));

		for(int i=0; i<n; i++) {
			var mult = multiplyPolynomial(ways, ways);
			{
				long val = 0;
				for(int j=mult.size()-1; j>=f+1; j--)
					val += mult.get(j);
				val %= MOD;
				suffix.set(f+1, val);
			}
			for(int j=f; j>=0; j--){
				long val = suffix.get(j+1) + mult.get(j);
				val = val>=MOD? val-MOD: val;
				suffix.set(j, val);
			}
			if(i < n-1) {
				for(int j=0; j <= k && j<=f; j++) {
					long val = suffix.get(j); // c_curr = j
					val += mult.get(j)*(k-j); // j+1 ~ k
					val %= MOD;
					ways.set(j, val);
				}
				{
					long val = suffix.get(f+1)*Math.max(0, k-f);
					val %= MOD;
					ways.set(f+1, val);
				}
			}
			else {
				ans = mult.get(f);
			}
		}

		return (int)ans;
	}

	static long pow(int a, int k, long p) {
		long m = k;
		long ans = 1;

		// curr = k^(2^i)
		long curr = a;

		// k^(2x+1) = (k^x)^2 * k
		while(m > 0) {
			if( (m&1) == 1 ) {
				ans *= curr;
				ans %= p;
			}
			m >>= 1;
			curr *= curr;
			curr %= p;
		}
		return ans;
	}

	// computes a^(p-2)
	static long inverse(int a, long p) {
		return pow(a, (int)(p-2), p);
	}

	// static final long MOD = 998_244_353; // = 1 + 7*17*2^23
	// primitive root is 3, i.e., the order of 3 is MOD-1
	// we have to find the 1<<23-th root
	static final int ROOT = (int) pow(3, 7*17, MOD);
	static final int ROOT_INV = (int) pow(ROOT, (int)MOD - 2, MOD);
	static final int ORDER = 1 << 23;

	static void fft(ArrayList<Long> a, boolean isInvertedFFT) {
	    int n = a.size();

	    for (int i = 1, j = 0; i < n; i++) {
	        int bit = n >> 1;
	        for (; (j & bit) > 0; bit >>= 1)
	            j ^= bit;
	        j ^= bit;

	        if (i < j) {
	        	Collections.swap(a, i, j);
	        }
	    }

	    for (int len = 2; len <= n; len <<= 1) {
	        long wlen = isInvertedFFT ? ROOT_INV : ROOT;
	        for (int i = len; i < ORDER; i <<= 1)
	            wlen = wlen * wlen % MOD;

	        for (int i = 0; i < n; i += len) {
	        	long w = 1;
	            for (int j = 0; j < len / 2; j++) {
	                long u = a.get(i+j);
	                long v = a.get(i+j+len/2) * w % MOD;
	                a.set(i+j,  u + v < MOD ? u + v : u + v - MOD);
	                a.set(i+j+len/2, u - v >= 0 ? u - v : u - v + MOD);
	                w = w * wlen % MOD;
	            }
	        }
	    }

	    if (isInvertedFFT) {
	        int inv = (int) inverse(n, MOD);
	        //a = (ArrayList<Long>) a.stream().map(x -> x*inv%MOD).collect(Collectors.toList());
	        var iter = a.listIterator();
	        while(iter.hasNext()) {
	        	iter.set(iter.next()*inv%MOD);
	        }
	    }
	}

	static ArrayList<Long> multiplyPolynomial(ArrayList<Long> a, ArrayList<Long> b) {
		ArrayList<Long> fa = (ArrayList<Long>) a.clone();
		ArrayList<Long> fb = (ArrayList<Long>) b.clone();
	    int n = 1;
	    while (n < a.size() + b.size())
	        n <<= 1;
	    for(int i=fa.size(); i<n; i++)
	    	fa.add(0l);
	    for(int i=fb.size(); i<n; i++)
	    	fb.add(0l);

	    fft(fa, false);
	    fft(fb, false);
	    for (int i = 0; i < n; i++)
	        fa.set(i, fa.get(i)*fb.get(i) % MOD);
	    fft(fa, true);

	    ArrayList<Long> result = new ArrayList<>(n);
	    for (int i = 0; i < n; i++)
	    	result.add(fa.get(i));
	    return result;
	}

	public static class MyScanner {
		BufferedReader br;
		StringTokenizer st;

		// 32768?
		public MyScanner(InputStream is, int bufferSize) {
			br = new BufferedReader(new InputStreamReader(is), bufferSize);
		}

		public MyScanner(InputStream is) {
			br = new BufferedReader(new InputStreamReader(is));
			// br = new BufferedReader(new InputStreamReader(System.in));
			// br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
		}

		public void close() {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

		String next() {
			while (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

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

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

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

		String nextLine(){
			String str = "";
			try {
				str = br.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return str;
		}

		int[][] nextTreeEdges(int n, int offset){
			int[][] e = new int[n-1][2];
			for(int i=0; i<n-1; i++){
				e[i][0] = nextInt()+offset;
				e[i][1] = nextInt()+offset;
			}
			return e;
		}

		int[][] nextMatrix(int n, int m) {
			return nextMatrix(n, m, 0);
		}

		int[][] nextMatrix(int n, int m, int offset) {
			int[][] mat = new int[n][m];
			for(int i=0; i<n; i++) {
				for(int j=0; j<m; j++) {
					mat[i][j] = nextInt()+offset;
				}
			}
			return mat;
		}

		int[][] nextPairs(int n){
			return nextPairs(n, 0);
		}

		int[][] nextPairs(int n, int offset) {
			int[][] xy = new int[2][n];
			for(int i=0; i<n; i++) {
				xy[0][i] = nextInt() + offset;
				xy[1][i] = nextInt() + offset;
			}
			return xy;
		}

		int[][] nextGraphEdges(){
			return nextGraphEdges(0);
		}

		int[][] nextGraphEdges(int offset) {
			int m = nextInt();
			int[][] e = new int[m][2];
			for(int i=0; i<m; i++){
				e[i][0] = nextInt()+offset;
				e[i][1] = nextInt()+offset;
			}
			return e;
		}

		int[] nextIntArray(int len) {
			return nextIntArray(len, 0);
		}
		int[] nextIntArray(int len, int offset){
	    	int[] a = new int[len];
			for(int j=0; j<len; j++)
	    		a[j] = nextInt()+offset;
	    	return a;
		}

		long[] nextLongArray(int len) {
			return nextLongArray(len, 0);
		}
		long[] nextLongArray(int len, int offset){
	    	long[] a = new long[len];
			for(int j=0; j<len; j++)
	    		a[j] = nextLong()+offset;
	    	return a;
		}
	}

	public static class MyPrintWriter extends PrintWriter{
		public MyPrintWriter(OutputStream os) {
			super(os);
		}

		public void printlnAns(long ans) {
			println(ans);
		}

		public void printlnAns(int ans) {
			println(ans);
		}

		public void printlnAns(boolean ans) {
			if(ans)
				println(YES);
			else
				println(NO);
		}

		public void printAns(long[] arr){
			if(arr != null && arr.length > 0){
				print(arr[0]);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]);
				}
			}
		}
		public void printlnAns(long[] arr){
			printAns(arr);
			println();
		}

		public void printAns(int[] arr){
			if(arr != null && arr.length > 0){
				print(arr[0]);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]);
				}
			}
		}
		public void printlnAns(int[] arr){
			printAns(arr);
			println();
		}

		public <T> void printAns(ArrayList<T> arr){
			if(arr != null && arr.size() > 0){
				print(arr.get(0));
				for(int i=1; i<arr.size(); i++){
					print(" ");
					print(arr.get(i));
				}
			}
		}
		public <T> void printlnAns(ArrayList<T> arr){
			printAns(arr);
			println();
		}

		public void printAns(int[] arr, int add){
			if(arr != null && arr.length > 0){
				print(arr[0]+add);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]+add);
				}
			}
		}
		public void printlnAns(int[] arr, int add){
			printAns(arr, add);
			println();
		}

		public void printAns(ArrayList<Integer> arr, int add) {
			if(arr != null && arr.size() > 0){
				print(arr.get(0)+add);
				for(int i=1; i<arr.size(); i++){
					print(" ");
					print(arr.get(i)+add);
				}
			}
		}

		public void printlnAns(ArrayList<Integer> arr, int add){
			printAns(arr, add);
			println();
		}

		public void printlnAnsSplit(long[] arr, int split){
			if(arr != null){
				for(int i=0; i<arr.length; i+=split){
					print(arr[i]);
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr[j]);
					}
					println();
				}
			}
		}

		public void printlnAnsSplit(int[] arr, int split){
			if(arr != null){
				for(int i=0; i<arr.length; i+=split){
					print(arr[i]);
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr[j]);
					}
					println();
				}
			}
		}

		public <T> void printlnAnsSplit(ArrayList<T> arr, int split){
			if(arr != null && !arr.isEmpty()){
				for(int i=0; i<arr.size(); i+=split){
					print(arr.get(i));
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr.get(j));
					}
					println();
				}
			}
		}
	}

	static private void permutateAndSort(long[] a) {
		int n = a.length;
		Random R = new Random(System.currentTimeMillis());
		for(int i=0; i<n; i++) {
			int t = R.nextInt(n-i);
			long temp = a[n-1-i];
			a[n-1-i] = a[t];
			a[t] = temp;
		}
		Arrays.sort(a);
	}

	static private void permutateAndSort(int[] a) {
		int n = a.length;
		Random R = new Random(System.currentTimeMillis());
		for(int i=0; i<n; i++) {
			int t = R.nextInt(n-i);
			int temp = a[n-1-i];
			a[n-1-i] = a[t];
			a[t] = temp;
		}
		Arrays.sort(a);
	}

	static private int[][] constructChildren(int n, int[] parent, int parentRoot){
		int[][] childrens = new int[n][];

		int[] numChildren = new int[n];
		for(int i=0; i<parent.length; i++) {
			if(parent[i] != parentRoot)
				numChildren[parent[i]]++;
		}

		for(int i=0; i<n; i++) {
			childrens[i] = new int[numChildren[i]];
		}

		int[] idx = new int[n];
		for(int i=0; i<parent.length; i++) {
			if(parent[i] != parentRoot)
				childrens[parent[i]][idx[parent[i]]++] = i;
		}

		return childrens;
	}

	static private int[][][] constructDirectedNeighborhood(int n, int[][] e){
		int[] inDegree = new int[n];
		int[] outDegree = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			outDegree[u]++;
			inDegree[v]++;
		}

		int[][] inNeighbors = new int[n][];
		int[][] outNeighbors = new int[n][];
		for(int i=0; i<n; i++) {
			inNeighbors[i] = new int[inDegree[i]];
			outNeighbors[i] = new int[outDegree[i]];
		}

		int[] inIdx = new int[n];
		int[] outIdx = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			outNeighbors[u][outIdx[u]++] = v;
			inNeighbors[v][inIdx[v]++] = u;
		}

		return new int[][][] {inNeighbors, outNeighbors};
	}

	static private int[][] constructNeighborhood(int n, int[][] e) {
		int[] degree = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			degree[u]++;
			degree[v]++;
		}

		int[][] neighbors = new int[n][];
		for(int i=0; i<n; i++)
			neighbors[i] = new int[degree[i]];

		int[] idx = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			neighbors[u][idx[u]++] = v;
			neighbors[v][idx[v]++] = u;
		}

		return neighbors;
	}

	static private void drawGraph(int[][] e) {
		makeDotUndirected(e);
		try {
			final Process process = new ProcessBuilder("dot", "-Tpng", "graph.dot")
					.redirectOutput(new File("graph.png"))
					.start();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

	static private void makeDotUndirected(int[][] e) {
		MyPrintWriter out2 = null;
		 try {
			out2 = new MyPrintWriter(new FileOutputStream("graph.dot"));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		out2.println("strict graph {");
		for(int i=0; i<e.length; i++){
			out2.println(e[i][0] + "--" + e[i][1] + ";");
		}
		out2.println("}");
		out2.close();
	}

	static private void makeDotDirected(int[][] e) {
		MyPrintWriter out2 = null;
		 try {
			out2 = new MyPrintWriter(new FileOutputStream("graph.dot"));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		out2.println("strict digraph {");
		for(int i=0; i<e.length; i++){
			out2.println(e[i][0] + "->" + e[i][1] + ";");
		}
		out2.println("}");
		out2.close();
	}

}


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

// you can compare with output.txt and expected out
public class RoundEdu132F {
	MyPrintWriter out;
	MyScanner in;

//	final static long FIXED_RANDOM;
//	static {
//		FIXED_RANDOM = System.currentTimeMillis();
//	}
	final static String IMPOSSIBLE = "IMPOSSIBLE";
	final static String POSSIBLE = "POSSIBLE";
	final static String YES = "YES";
	final static String NO = "NO";

    private void initIO(boolean isFileIO) {
        if (System.getProperty("ONLINE_JUDGE") == null && isFileIO) {
        	try{
	            in = new MyScanner(new FileInputStream("input.txt"));
	            out = new MyPrintWriter(new FileOutputStream("output.txt"));
        	}
        	catch(FileNotFoundException e){
        		e.printStackTrace();
        	}
        }
        else{
    		in = new MyScanner(System.in);
    	    out = new MyPrintWriter(new BufferedOutputStream(System.out));
        }
    }

	public static void main(String[] args){
//		Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in)));

		RoundEdu132F sol = new RoundEdu132F();
		sol.run();
    }

	private void run() {
		boolean isDebug = false;
		boolean isFileIO = true;
		boolean hasMultipleTests = false;

		initIO(isFileIO);

		int t = hasMultipleTests? in.nextInt() : 1;

	    for (int i = 1; i <= t; ++i) {
	    	if(isDebug){
		    	out.printf("Test %d\n", i);
	    	}

	    	getInput();

	    	ans = solve();

	    	printOutput();
	    }

	    in.close();
	    out.close();
	}

	int n, k, f;
	void getInput() {
		n = in.nextInt();
		k = in.nextInt();
		f = in.nextInt();
	}

	void printOutput() {
		out.printlnAns(ans);
	}

	static final long MOD = 998244353;
	int ans;
	int solve(){
		long ans = 0;

		// for each binary string s,
		// consider binary strings t of length n, where s is a prefix of t
		// we can have <= c_s among t

		// it's a full binary tree
		// where each vertex contains # of records in its subtree
		// and all records are at depth n

		// from each leaf, go up again, update each vertex to min(val, val(child1) + val(child2))
		// then the val(root) must be exactly f
		// where root is null string

		// the problem in this counting is we would have to use inclusion-exclusion due to duplicate cases
		// so we choose vertices representing disjoint subtrees
		// whose union can represent the whole tree
		// and whose sum is exactly f

		// for vertices under the subtrees, we can freely choose val
		// so that sum of siblings in each subtree >= val of root of subtree
		// for vertices above the subtrees, we can freely choose val between sum and k

		// so another approach:
		// for each vertex v of depth h
		// find # of ways to make sum exactly x
		// case 1: val(v) = x
		// add up ways(l, y)*ways(r, z) where y+z >= x
		// case 2: val(v) >= x+1
		// add up ways(l, y)*ways(r, z) where y+z = x

		// takes up space: n*k*2 <= 30k = 6*10^6 < 100MB
		// time: O(nk), should fit in 6s

		// 2 1 1
		// case 1: c_0 = 1, c_1 = 0
		// 00 01 10 11
		// 1  0  0/1 0/1
		// 0  1  0/1 0/1
		// 1  1  0/1 0/1
		// -> 12

		// case 2: c_0 = 0, c_1 = 1
		// -> 12

		// case 3: c_0 = 1, c_1 = 1
		// 1 0 0 0
		// 0 1 0 0
		// 1 1 0 0
		// 0 0 1 0
		// 0 0 0 1
		// 0 0 1 1
		// -> 6

		// subtree_0 = 1 -> 3
		// c_0 = 1 -> 1 0, 0 1, 1 1

		// subtree_0 = 0 -> 5
		// c_0 = 0 -> 0/1, 0/1 -> 4
		// c_0 = 1 -> 0, 0 -> 1
		// 3*5 + 3*5 = 30

		// subtree_l = 0 -> 1
		// subtree_l = 1 -> 1

		long[] ways = new long[f+2];
		long[] suffix = new long[f+2];

		for(int i=0; i<=k && i<=f; i++)
			ways[i] = 1;
		ways[f+1] = Math.max(0, k-f);

		for(int i=0; i<n; i++) {
			long[] mult = multiplyPolynomial(ways, ways);
			{
				long val = 0;
				for(int j=mult.length-1; j>=f+1; j--)
					val += mult[j];
				val %= MOD;
				suffix[f+1] = val;
			}
			for(int j=f; j>=0; j--){
				long val = suffix[j+1] + mult[j];
				val = val>=MOD? val-MOD: val;
				suffix[j] = val;
			}
			if(i < n-1) {
				for(int j=0; j <= k && j<=f; j++) {
					long val = suffix[j]; // c_curr = j
					val += mult[j]*(k-j); // j+1 ~ k
					val %= MOD;
					ways[j] = val;
				}
				{
					long val = suffix[f+1]*Math.max(0, k-f);
					val %= MOD;
					ways[f+1] = val;
				}
			}
			else {
				ans = mult[f];
			}
		}

		return (int)ans;
	}

	static long pow(int a, int k, long p) {
		long m = k;
		long ans = 1;

		// curr = k^(2^i)
		long curr = a;

		// k^(2x+1) = (k^x)^2 * k
		while(m > 0) {
			if( (m&1) == 1 ) {
				ans *= curr;
				ans %= p;
			}
			m >>= 1;
			curr *= curr;
			curr %= p;
		}
		return ans;
	}

	// computes a^(p-2)
	static long inverse(int a, long p) {
		return pow(a, (int)(p-2), p);
	}

	// static final long MOD = 998_244_353; // = 1 + 7*17*2^23
	// primitive root is 3, i.e., the order of 3 is MOD-1
	// we have to find the 1<<23-th root
	static final int ROOT = (int) pow(3, 7*17, MOD);
	static final int ROOT_INV = (int) pow(ROOT, (int)MOD - 2, MOD);
	static final int ORDER = 1 << 23;

	static void swap(long[] a, int i, int j) {
		long temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
	static void fft(long[] a, boolean isInvertedFFT) {
	    int n = a.length;

	    for (int i = 1, j = 0; i < n; i++) {
	        int bit = n >> 1;
	        for (; (j & bit) > 0; bit >>= 1)
	            j ^= bit;
	        j ^= bit;

	        if (i < j) {
	        	swap(a, i, j);
	        }
	    }

	    for (int len = 2; len <= n; len <<= 1) {
	        long wlen = isInvertedFFT ? ROOT_INV : ROOT;
	        for (int i = len; i < ORDER; i <<= 1)
	            wlen = wlen * wlen % MOD;

	        for (int i = 0; i < n; i += len) {
	        	long w = 1;
	            for (int j = 0; j < len / 2; j++) {
	                long u = a[i+j];
	                long v = a[i+j+len/2] * w % MOD;
	                a[i+j] =  u + v < MOD ? u + v : u + v - MOD;
	                a[i+j+len/2] = u - v >= 0 ? u - v : u - v + MOD;
	                w = w * wlen % MOD;
	            }
	        }
	    }

	    if (isInvertedFFT) {
	        int inv = (int) inverse(n, MOD);
	        for(int i=0; i<a.length; i++)
	        	a[i] = a[i]*inv%MOD;
	    }
	}

	static long[] multiplyPolynomial(long[] a, long[] b) {
	    int n = 1;
	    while (n < a.length + b.length)
	        n <<= 1;
		long[] fa = Arrays.copyOf(a, n);
		long[] fb = Arrays.copyOf(b, n);

	    fft(fa, false);
	    fft(fb, false);
	    for (int i = 0; i < n; i++)
	        fa[i] = fa[i]*fb[i] % MOD;
	    fft(fa, true);

	    return fa;
	}

	public static class MyScanner {
		BufferedReader br;
		StringTokenizer st;

		// 32768?
		public MyScanner(InputStream is, int bufferSize) {
			br = new BufferedReader(new InputStreamReader(is), bufferSize);
		}

		public MyScanner(InputStream is) {
			br = new BufferedReader(new InputStreamReader(is));
			// br = new BufferedReader(new InputStreamReader(System.in));
			// br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
		}

		public void close() {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

		String next() {
			while (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

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

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

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

		String nextLine(){
			String str = "";
			try {
				str = br.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return str;
		}

		int[][] nextTreeEdges(int n, int offset){
			int[][] e = new int[n-1][2];
			for(int i=0; i<n-1; i++){
				e[i][0] = nextInt()+offset;
				e[i][1] = nextInt()+offset;
			}
			return e;
		}

		int[][] nextMatrix(int n, int m) {
			return nextMatrix(n, m, 0);
		}

		int[][] nextMatrix(int n, int m, int offset) {
			int[][] mat = new int[n][m];
			for(int i=0; i<n; i++) {
				for(int j=0; j<m; j++) {
					mat[i][j] = nextInt()+offset;
				}
			}
			return mat;
		}

		int[][] nextPairs(int n){
			return nextPairs(n, 0);
		}

		int[][] nextPairs(int n, int offset) {
			int[][] xy = new int[2][n];
			for(int i=0; i<n; i++) {
				xy[0][i] = nextInt() + offset;
				xy[1][i] = nextInt() + offset;
			}
			return xy;
		}

		int[][] nextGraphEdges(){
			return nextGraphEdges(0);
		}

		int[][] nextGraphEdges(int offset) {
			int m = nextInt();
			int[][] e = new int[m][2];
			for(int i=0; i<m; i++){
				e[i][0] = nextInt()+offset;
				e[i][1] = nextInt()+offset;
			}
			return e;
		}

		int[] nextIntArray(int len) {
			return nextIntArray(len, 0);
		}
		int[] nextIntArray(int len, int offset){
	    	int[] a = new int[len];
			for(int j=0; j<len; j++)
	    		a[j] = nextInt()+offset;
	    	return a;
		}

		long[] nextLongArray(int len) {
			return nextLongArray(len, 0);
		}
		long[] nextLongArray(int len, int offset){
	    	long[] a = new long[len];
			for(int j=0; j<len; j++)
	    		a[j] = nextLong()+offset;
	    	return a;
		}
	}

	public static class MyPrintWriter extends PrintWriter{
		public MyPrintWriter(OutputStream os) {
			super(os);
		}

		public void printlnAns(long ans) {
			println(ans);
		}

		public void printlnAns(int ans) {
			println(ans);
		}

		public void printlnAns(boolean ans) {
			if(ans)
				println(YES);
			else
				println(NO);
		}

		public void printAns(long[] arr){
			if(arr != null && arr.length > 0){
				print(arr[0]);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]);
				}
			}
		}
		public void printlnAns(long[] arr){
			printAns(arr);
			println();
		}

		public void printAns(int[] arr){
			if(arr != null && arr.length > 0){
				print(arr[0]);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]);
				}
			}
		}
		public void printlnAns(int[] arr){
			printAns(arr);
			println();
		}

		public <T> void printAns(ArrayList<T> arr){
			if(arr != null && arr.size() > 0){
				print(arr.get(0));
				for(int i=1; i<arr.size(); i++){
					print(" ");
					print(arr.get(i));
				}
			}
		}
		public <T> void printlnAns(ArrayList<T> arr){
			printAns(arr);
			println();
		}

		public void printAns(int[] arr, int add){
			if(arr != null && arr.length > 0){
				print(arr[0]+add);
				for(int i=1; i<arr.length; i++){
					print(" ");
					print(arr[i]+add);
				}
			}
		}
		public void printlnAns(int[] arr, int add){
			printAns(arr, add);
			println();
		}

		public void printAns(ArrayList<Integer> arr, int add) {
			if(arr != null && arr.size() > 0){
				print(arr.get(0)+add);
				for(int i=1; i<arr.size(); i++){
					print(" ");
					print(arr.get(i)+add);
				}
			}
		}

		public void printlnAns(ArrayList<Integer> arr, int add){
			printAns(arr, add);
			println();
		}

		public void printlnAnsSplit(long[] arr, int split){
			if(arr != null){
				for(int i=0; i<arr.length; i+=split){
					print(arr[i]);
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr[j]);
					}
					println();
				}
			}
		}

		public void printlnAnsSplit(int[] arr, int split){
			if(arr != null){
				for(int i=0; i<arr.length; i+=split){
					print(arr[i]);
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr[j]);
					}
					println();
				}
			}
		}

		public <T> void printlnAnsSplit(ArrayList<T> arr, int split){
			if(arr != null && !arr.isEmpty()){
				for(int i=0; i<arr.size(); i+=split){
					print(arr.get(i));
					for(int j=i+1; j<i+split; j++){
						print(" ");
						print(arr.get(j));
					}
					println();
				}
			}
		}
	}

	static private void permutateAndSort(long[] a) {
		int n = a.length;
		Random R = new Random(System.currentTimeMillis());
		for(int i=0; i<n; i++) {
			int t = R.nextInt(n-i);
			long temp = a[n-1-i];
			a[n-1-i] = a[t];
			a[t] = temp;
		}
		Arrays.sort(a);
	}

	static private void permutateAndSort(int[] a) {
		int n = a.length;
		Random R = new Random(System.currentTimeMillis());
		for(int i=0; i<n; i++) {
			int t = R.nextInt(n-i);
			int temp = a[n-1-i];
			a[n-1-i] = a[t];
			a[t] = temp;
		}
		Arrays.sort(a);
	}

	static private int[][] constructChildren(int n, int[] parent, int parentRoot){
		int[][] childrens = new int[n][];

		int[] numChildren = new int[n];
		for(int i=0; i<parent.length; i++) {
			if(parent[i] != parentRoot)
				numChildren[parent[i]]++;
		}

		for(int i=0; i<n; i++) {
			childrens[i] = new int[numChildren[i]];
		}

		int[] idx = new int[n];
		for(int i=0; i<parent.length; i++) {
			if(parent[i] != parentRoot)
				childrens[parent[i]][idx[parent[i]]++] = i;
		}

		return childrens;
	}

	static private int[][][] constructDirectedNeighborhood(int n, int[][] e){
		int[] inDegree = new int[n];
		int[] outDegree = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			outDegree[u]++;
			inDegree[v]++;
		}

		int[][] inNeighbors = new int[n][];
		int[][] outNeighbors = new int[n][];
		for(int i=0; i<n; i++) {
			inNeighbors[i] = new int[inDegree[i]];
			outNeighbors[i] = new int[outDegree[i]];
		}

		int[] inIdx = new int[n];
		int[] outIdx = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			outNeighbors[u][outIdx[u]++] = v;
			inNeighbors[v][inIdx[v]++] = u;
		}

		return new int[][][] {inNeighbors, outNeighbors};
	}

	static private int[][] constructNeighborhood(int n, int[][] e) {
		int[] degree = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			degree[u]++;
			degree[v]++;
		}

		int[][] neighbors = new int[n][];
		for(int i=0; i<n; i++)
			neighbors[i] = new int[degree[i]];

		int[] idx = new int[n];
		for(int i=0; i<e.length; i++) {
			int u = e[i][0];
			int v = e[i][1];
			neighbors[u][idx[u]++] = v;
			neighbors[v][idx[v]++] = u;
		}

		return neighbors;
	}

	static private void drawGraph(int[][] e) {
		makeDotUndirected(e);
		try {
			final Process process = new ProcessBuilder("dot", "-Tpng", "graph.dot")
					.redirectOutput(new File("graph.png"))
					.start();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

	static private void makeDotUndirected(int[][] e) {
		MyPrintWriter out2 = null;
		 try {
			out2 = new MyPrintWriter(new FileOutputStream("graph.dot"));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		out2.println("strict graph {");
		for(int i=0; i<e.length; i++){
			out2.println(e[i][0] + "--" + e[i][1] + ";");
		}
		out2.println("}");
		out2.close();
	}

	static private void makeDotDirected(int[][] e) {
		MyPrintWriter out2 = null;
		 try {
			out2 = new MyPrintWriter(new FileOutputStream("graph.dot"));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		out2.println("strict digraph {");
		for(int i=0; i<e.length; i++){
			out2.println(e[i][0] + "->" + e[i][1] + ";");
		}
		out2.println("}");
		out2.close();
	}

}