import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;

public class CF1153F {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        int mod = 998244353;
        int[][][] mem;
        boolean[][][] visit;
        int l1;
        int l2;
        int l3;
        int n;
        int k;
        int time;

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        public void solve() {
            n = io.readInt();
            k = io.readInt();
            int l = io.readInt();
            mem = new int[2][n + 1][n + 1];
            visit = new boolean[2][n + 1][n + 1];
            int meetCount = find(n, n, 1);

            int factorial = 1;
            for (int i = 2, until = 2 * n + 1; i <= until; i++) {
                factorial = mul(factorial, i);
            }
            int total = mul(factorial, Mathematics.inverse(Mathematics.pow(2, n, mod), mod));
            int probability = mul(meetCount, Mathematics.inverse(total, mod));
            int expectLength = mul(l, probability);
            io.cache.append(expectLength);
        }

        public int add(int a, int b) {
            return (a + b) % mod;
        }

        public int sub(int a, int b) {
            if (a >= b) {
                return a - b;
            }
            return a - b + mod;
        }

        public int mul(int a, int b) {
            return (int) (((long) a * b) % mod);
        }

        public int find(int i, int j, int x) {
            time++;
            if (i < 0 || i > n || j < 0 || j > n) {
                return 0;
            }
            if (i == 0 && j == 0 && x == 0) {
                return 1;
            }
            if (visit[x][i][j]) {
                return mem[x][i][j];
            }
            visit[x][i][j] = true;
            mem[x][i][j] = 0;
            if (i < j) {
                return 0;
            }
            if (x == 1) {
                mem[x][i][j] = (mem[x][i][j] + find(i, j, 0) * (i - j >= k ? 1 : 0)) % mod;
            }
            mem[x][i][j] = (int) ((mem[x][i][j] + (long) (n - i + 1) * find(i - 1, j, x)) % mod);
            mem[x][i][j] = (int)((mem[x][i][j] + (long)(i - j + 1) * find(i, j - 1, x)) % mod);
            return mem[x][i][j];
        }
    }

    public static class Mathematics {

        public static int ceilPowerOf2(int x) {
            return 32 - Integer.numberOfLeadingZeros(x - 1);
        }

        public static int floorPowerOf2(int x) {
            return 31 - Integer.numberOfLeadingZeros(x);
        }

        public static long modmul(long a, long b, long mod) {
            return b == 0 ? 0 : ((modmul(a, b >> 1, mod) << 1) % mod + a * (b & 1)) % mod;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static int gcd(int a, int b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static int gcd0(int a, int b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static int extgcd(int a, int b, int[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                int g = extgcd0(b, a, coe);
                int tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static int extgcd0(int a, int b, int[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            int g = extgcd0(b, a % b, coe);
            int n = coe[0];
            int m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static long gcd(long a, long b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static long gcd0(long a, long b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static long extgcd(long a, long b, long[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                long g = extgcd0(b, a, coe);
                long tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static long extgcd0(long a, long b, long[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            long g = extgcd0(b, a % b, coe);
            long n = coe[0];
            long m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get y where x * y = 1 (% mod)
         */
        public static int inverse(int x, int mod) {
            return pow(x, mod - 2, mod);
        }

        /**
         * Get x^n(% mod)
         */
        public static int pow(int x, int n, int mod) {
            n = mod(n, mod - 1);
            x = mod(x, mod);
            int bit = 31 - Integer.numberOfLeadingZeros(n);
            long product = 1;
            for (; bit >= 0; bit--) {
                product = product * product % mod;
                if (((1 << bit) & n) != 0) {
                    product = product * x % mod;
                }
            }
            return (int) product;
        }

        public static long longpow(long x, long n, long mod) {
            if (n == 0) {
                return 1;
            }
            long prod = longpow(x, n >> 1, mod);
            prod = modmul(prod, prod, mod);
            if ((n & 1) == 1) {
                prod = modmul(prod, x, mod);
            }
            return prod;
        }

        /**
         * Get x % mod
         */
        public static int mod(int x, int mod) {
            return x >= 0 ? x % mod : (((x % mod) + mod) % mod);
        }

        /**
         * Get n!/(n-m)!
         */
        public static long permute(int n, int m) {
            return m == 0 ? 1 : n * permute(n - 1, m - 1);
        }

        /**
         * Put all primes less or equal to limit into primes after offset
         */
        public static int eulerSieve(int limit, int[] primes, int offset) {
            boolean[] isComp = new boolean[limit + 1];
            int wpos = offset;
            for (int i = 2; i <= limit; i++) {
                if (!isComp[i]) {
                    primes[wpos++] = i;
                }
                for (int j = offset, until = limit / i; j < wpos && primes[j] <= until; j++) {
                    int pi = primes[j] * i;
                    isComp[pi] = true;
                    if (i % primes[j] == 0) {
                        break;
                    }
                }
            }
            return wpos - offset;
        }

        /**
         * Round x into integer
         */
        public static int intRound(double x) {
            if (x < 0) {
                return -(int) (-x + 0.5);
            }
            return (int) (x + 0.5);
        }

        /**
         * Round x into long
         */
        public static long longRound(double x) {
            if (x < 0) {
                return -(long) (-x + 0.5);
            }
            return (long) (x + 0.5);
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

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

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

        public int readInt() {
            int sign = 1;

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

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

            return val;
        }

        public long readLong() {
            int sign = 1;

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

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

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1153F {
	static final int MD = 998244353;
	static int[][] ch;
	static void init(int n) {
		ch = new int[1 + n][1 + n];
		ch[0][0] = 1;
		for (int i = 1; i <= n; i++) {
			ch[i][0] = 1;
			for (int j = 1; j <= i; j++)
				ch[i][j] = (ch[i - 1][j] + ch[i - 1][j - 1]) % MD;
		}
	}
	static long power(int a, int k) {
		if (k == 0)
			return 1;
		long p = power(a, k / 2);
		p = p * p % MD;
		if (k % 2 == 1)
			p = p * a % MD;
		return p;
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		int l = Integer.parseInt(st.nextToken());
		init(n);
		long[] pp = new long[1 + n + n];
		long[] qq = new long[1 + n + n];
		pp[n] = power(2, n);
		for (int i = 0; i < n; i++)
			for (int j = n + n; j > 0; j--)
				pp[j] = (pp[j] - pp[j - 1]) % MD;
		long[] aa = new long[1 + n + n];
		for (int j = 0; j <= n + n; j++)
			aa[j] = pp[j];
		long inv2 = (MD + 1) / 2;
		for (int i = 1; i <= n - k; i++) {
			// qq := pp / p, where p = 2x (1 - x)
			// divide by 2x
			for (int j = 0; j < n + n; j++)
				qq[j] = pp[j + 1] * inv2 % MD;
			qq[n + n] = 0;
			// divide by 1 - x is multiply by 1 + x + x^2 + x^3 + ...
			for (int j = 1; j <= n + n; j++)
				qq[j] = (qq[j] + qq[j - 1]) % MD;
			// pp := pp * (1 - p) / p = pp / p - pp = qq - pp
			for (int j = 0; j <= n + n; j++)
				pp[j] = (qq[j] - pp[j]) % MD;
			long a = ch[n][i];
			for (int j = 0; j <= n + n; j++)
				aa[j] = (aa[j] + a * pp[j]) % MD;
		}
		// integrate x^i to x^{i + 1} / (i + 1)
		long a = 0;
		for (int i = 0; i <= n + n; i++)
			a = (a + aa[i] * power(i + 1, MD - 2)) % MD;
		a = (a * l % MD + MD) % MD;
		System.out.println(a);
	}
}


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

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

    static class F {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.ni(), k = in.ni(), l = in.ni();
            int mod = 998244353;
            long[] invs = IntegerUtils.invs(2 * n + 3, mod);
            long[][] p = new long[2 * n + 1][n + 1];
            p[0][1] = 1; // first is always started
            for (int i = 1; i < 2 * n; i++) {
                int prevMaxRunning = Math.min(2 * n - i, i); // how many intervals max were running (covering)
                int maxRunning = Math.min(2 * n - i - 1, i + 1); // how many intervals max can be running
                for (int j = 0; j <= prevMaxRunning; j++) {
                    if (p[i - 1][j] != 0) {
                        if (j > 0) {
                            p[i][j - 1] = (p[i][j - 1] + p[i - 1][j] * j % mod * invs[2 * n - i] % mod) % mod; // close an interval
                        }
                        if (j < maxRunning) {
                            p[i][j + 1] = (p[i][j + 1] + p[i - 1][j] * (2 * n - i - j) % mod * invs[2 * n - i] % mod) % mod; // start a new interval
                        }
                    }
                }
            }
            long ans = 0;
            for (int i = 0; i < 2 * n; i++) {
                for (int j = k; j <= n; j++) {
                    if (p[i][j] == 0)
                        continue;
                    ans = (ans + p[i][j]) % mod;
                }
            }
            ans = ans * l % mod * invs[2 * n + 1] % mod;
            out.println(ans);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

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

        public int ni() {
            return Integer.parseInt(ns());
        }

    }

    static class IntegerUtils {
        public static long[] invs(int n, long p) {
            long[] res = new long[n];
            res[1] = 1;
            for (int i = 2; i < n; i++) {
                res[i] = (p - (p / i) * res[(int) (p % i)] % p) % p;
            }
            return res;
        }

    }
}


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

public class Codeforces1153F {

	public static void main(String[] args) throws IOException {
		int P = 998244353;

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int real_k = Integer.parseInt(st.nextToken());
		int l = Integer.parseInt(st.nextToken());

		//generate factorials
		int[] factorials = new int[2*n+2];
		factorials[0] = 1;
		for (int i = 1; i <= 2*n+1; i++) {
			factorials[i] = multiply(factorials[i-1], i, P);
		}

		//number of ways to choose k pairs from 2k elements
		//where order doesn't matter
		//equals (2k)!/(2^n)/k! = (2k-1)!!
		int[] doublefact = new int[n+1];
		doublefact[0] = 1;
		for (int i = 1; i <= n; i++) {
			doublefact[i] = multiply(doublefact[i-1], (2*i-1), P);
		}

		//list[r][k] stores for rth segment, exactly k of the n segments covering it
		int[][] list = new int[2*n+2][n+1];

		for (int r = 1; r <= 2*n+1; r++) {
			for (int k = 1; k <= n; k++) {
				if (((r%2) != (k%2)) && (r-1 >= k) && (2*n+1-r >= k)) {
					int num = multiply(factorials[r-1], factorials[2*n+1-r], P);
					num = multiply(num, doublefact[(r-k-1)/2], P);
					num = multiply(num, doublefact[(2*n+1-r-k)/2], P);

					int denom = multiply(factorials[r-k-1], factorials[2*n+1-r-k], P);
					denom = multiply(denom, factorials[k], P);

					list[r][k] = multiply(num, inverse(multiply(denom, doublefact[n], P), P), P);
				}

			}
		}

		int ans = 0;
		for (int r = 1; r <= 2*n+1; r++) {
			for (int k = real_k; k <= n; k++) {
				ans += list[r][k];
				ans %= P;
			}
		}

		ans = multiply(ans, l, P);
		ans = multiply(ans, inverse(2*n+1, P), P);

		System.out.println(ans);

	}

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

	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));
		}

	}

}


//package round551;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class F {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), K = ni(), L = ni();
		int mod = 998244353;
		int[][] fif = enumFIF(10000, mod);
		long[] muls = new long[n+1];
		for(int i = K;i <= n;i++){
			long m = C(n, i, mod, fif);
			for(int j = i;j <= n;j++){
				muls[j] += m * C(n-i, n-j, mod, fif) * ((j-i) % 2 == 0 ? 1 : -1);
				muls[j] %= mod;
			}
		}
		/*
\int_0^1 D(t) * (2x(1-x))^t dx
D(t) *
2^t * (t!)^2 / (2t+1)!
		 *
		 */

		long ans = 0;
		for(int i = K;i <= n;i++){
			ans +=
			pow(2, i, mod) * fif[0][i] % mod * fif[0][i] % mod
			* fif[1][2*i+1] % mod * muls[i];
			ans %= mod;
		}
		if(ans < 0)ans += mod;
		out.println(ans*L%mod);
	}

	public static long C(int n, int r, int mod, int[][] fif) {
		if (n < 0 || r < 0 || r > n)
			return 0;
		return (long) fif[0][n] * fif[1][r] % mod * fif[1][n - r] % mod;
	}

	public static long pow(long a, long n, long mod) {
		//		a %= mod;
		long ret = 1;
		int x = 63 - Long.numberOfLeadingZeros(n);
		for (; x >= 0; x--) {
			ret = ret * ret % mod;
			if (n << 63 - x < 0)
				ret = ret * a % mod;
		}
		return ret;
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][] { f, invf };
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

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

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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

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

    static class F {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.ni(), k = in.ni(), l = in.ni();
            int mod = 998244353;
            long[] invs = IntegerUtils.invs(2 * n + 3, mod);
            long[][] p = new long[2 * n + 1][n + 1];
            p[0][1] = 1; // first is always started
            long ans = 0;
            for (int i = 1; i < 2 * n; i++) {
                int prevMaxRunning = Math.min(2 * n - i, i); // how many intervals max were running (covering)
                int maxRunning = Math.min(2 * n - i - 1, i + 1); // how many intervals max can be running
                for (int j = 0; j <= prevMaxRunning; j++) {
                    if (p[i - 1][j] != 0) {
                        if (j > 0) {
                            p[i][j - 1] = (p[i][j - 1] + p[i - 1][j] * j % mod * invs[2 * n - i] % mod) % mod; // close an interval
                        }
                        if (j < maxRunning) {
                            p[i][j + 1] = (p[i][j + 1] + p[i - 1][j] * (2 * n - i - j) % mod * invs[2 * n - i] % mod) % mod; // start a new interval
                        }
                        if (j >= k)
                            ans = (ans + p[i - 1][j]) % mod;
                    }
                }
            }
            if (k <= 1)
                ans += p[2 * n - 1][1];

            ans = ans * l % mod * invs[2 * n + 1] % mod;
            out.println(ans);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

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

        public int ni() {
            return Integer.parseInt(ns());
        }

    }

    static class IntegerUtils {
        public static long[] invs(int n, long p) {
            long[] res = new long[n];
            res[1] = 1;
            for (int i = 2; i < n; i++) {
                res[i] = (p - (p / i) * res[(int) (p % i)] % p) % p;
            }
            return res;
        }

    }
}


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

public class Main implements Runnable{
    public static void main(String[] args){
        //new Thread(null,new Main(),"Thread-1",1024*1024*10).start();
        new Main().run();
    }
    int mod=998244353;
    private void solve() throws Exception {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int n=in.nextInt(),k=in.nextInt(),l=in.nextInt();
        long[]fac=new long[n+1];
        fac[0]=1;
        for(int i=1;i<=n;i++){
            fac[i]=fac[i-1]*i%mod;
        }
        long[][]dp=new long[2*n+1][2*n+2];
        dp[0][0]=1;
        for(int i=1;i<=2*n;i++){
            for(int j=0;j<=Math.min(i,n);j++){
                if(j>0) dp[i][j]=(dp[i][j]+dp[i-1][j-1])%mod;
                dp[i][j]=(dp[i][j]+dp[i-1][j+1]*(j+1)%mod)%mod;
            }
        }
        long ans=0;
        for(int i=k;i<=2*n;i++){
            for(int j=k;j<=n;j++){
                ans=(ans+dp[i][j]*dp[2*n-i][j]%mod*fac[j]%mod)%mod;
            }
        }
        out.println(l*ans%mod*Pow(dp[2*n][0],mod-2)%mod*Pow(2*n+1,mod-2)%mod);
        out.flush();
    }
    long Pow(long a,long b){
        long ans=1;
        while(b>0){
            if((b&1)!=0)ans=(ans*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return ans;
    }
    @Override
    public void run() {
        try {
            solve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    class InputReader{
        StreamTokenizer tokenizer;
        public InputReader(InputStream stream){
            tokenizer=new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
            tokenizer.ordinaryChars(33,126);
            tokenizer.wordChars(33,126);
        }
        public String next() throws IOException {
            tokenizer.nextToken();
            return tokenizer.sval;
        }
        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }
        public boolean hasNext() throws IOException {
            int res=tokenizer.nextToken();
            tokenizer.pushBack();
            return res!=tokenizer.TT_EOF;
        }
    }
}


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;

public class CF1153F {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        int mod = 998244353;
        int[][][] mem;
        boolean[][][] visit;
        int l1;
        int l2;
        int l3;
        int n;
        int k;
        int time;

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        public void solve() {
            n = io.readInt();
            k = io.readInt();
            int l = io.readInt();
            mem = new int[2][n + 1][n + 1];
            visit = new boolean[2][n + 1][n + 1];
            int meetCount = find(n, n, 1);

            int factorial = 1;
            for (int i = 2, until = 2 * n + 1; i <= until; i++) {
                factorial = mul(factorial, i);
            }
            int total = mul(factorial, Mathematics.inverse(Mathematics.pow(2, n, mod), mod));
            int probability = mul(meetCount, Mathematics.inverse(total, mod));
            int expectLength = mul(l, probability);
            io.cache.append(expectLength);
        }

        public int add(int a, int b) {
            return (a + b) % mod;
        }

        public int sub(int a, int b) {
            if (a >= b) {
                return a - b;
            }
            return a - b + mod;
        }

        public int mul(int a, int b) {
            return (int) (((long) a * b) % mod);
        }

        public int find(int i, int j, int x) {
            time++;
            if (i < 0 || i > n || j < 0 || j > n) {
                return 0;
            }
            if (i == 0 && j == 0 && x == 0) {
                return 1;
            }
            if (visit[x][i][j]) {
                return mem[x][i][j];
            }
            visit[x][i][j] = true;
            mem[x][i][j] = 0;
            if (i < j) {
                return 0;
            }
            if (x == 1) {
                mem[x][i][j] = add(mem[x][i][j], mul(find(i, j, 0), (i - j >= k ? 1 : 0)));
            }
            mem[x][i][j] = add(mem[x][i][j], mul((n - i + 1), find(i - 1, j, x)));
            mem[x][i][j] = add(mem[x][i][j], mul((i - j + 1), find(i, j - 1, x)));
            return mem[x][i][j];
        }
    }

    public static class Mathematics {

        public static int ceilPowerOf2(int x) {
            return 32 - Integer.numberOfLeadingZeros(x - 1);
        }

        public static int floorPowerOf2(int x) {
            return 31 - Integer.numberOfLeadingZeros(x);
        }

        public static long modmul(long a, long b, long mod) {
            return b == 0 ? 0 : ((modmul(a, b >> 1, mod) << 1) % mod + a * (b & 1)) % mod;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static int gcd(int a, int b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static int gcd0(int a, int b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static int extgcd(int a, int b, int[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                int g = extgcd0(b, a, coe);
                int tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static int extgcd0(int a, int b, int[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            int g = extgcd0(b, a % b, coe);
            int n = coe[0];
            int m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static long gcd(long a, long b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static long gcd0(long a, long b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static long extgcd(long a, long b, long[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                long g = extgcd0(b, a, coe);
                long tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static long extgcd0(long a, long b, long[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            long g = extgcd0(b, a % b, coe);
            long n = coe[0];
            long m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get y where x * y = 1 (% mod)
         */
        public static int inverse(int x, int mod) {
            return pow(x, mod - 2, mod);
        }

        /**
         * Get x^n(% mod)
         */
        public static int pow(int x, int n, int mod) {
            n = mod(n, mod - 1);
            x = mod(x, mod);
            int bit = 31 - Integer.numberOfLeadingZeros(n);
            long product = 1;
            for (; bit >= 0; bit--) {
                product = product * product % mod;
                if (((1 << bit) & n) != 0) {
                    product = product * x % mod;
                }
            }
            return (int) product;
        }

        public static long longpow(long x, long n, long mod) {
            if (n == 0) {
                return 1;
            }
            long prod = longpow(x, n >> 1, mod);
            prod = modmul(prod, prod, mod);
            if ((n & 1) == 1) {
                prod = modmul(prod, x, mod);
            }
            return prod;
        }

        /**
         * Get x % mod
         */
        public static int mod(int x, int mod) {
            return x >= 0 ? x % mod : (((x % mod) + mod) % mod);
        }

        /**
         * Get n!/(n-m)!
         */
        public static long permute(int n, int m) {
            return m == 0 ? 1 : n * permute(n - 1, m - 1);
        }

        /**
         * Put all primes less or equal to limit into primes after offset
         */
        public static int eulerSieve(int limit, int[] primes, int offset) {
            boolean[] isComp = new boolean[limit + 1];
            int wpos = offset;
            for (int i = 2; i <= limit; i++) {
                if (!isComp[i]) {
                    primes[wpos++] = i;
                }
                for (int j = offset, until = limit / i; j < wpos && primes[j] <= until; j++) {
                    int pi = primes[j] * i;
                    isComp[pi] = true;
                    if (i % primes[j] == 0) {
                        break;
                    }
                }
            }
            return wpos - offset;
        }

        /**
         * Round x into integer
         */
        public static int intRound(double x) {
            if (x < 0) {
                return -(int) (-x + 0.5);
            }
            return (int) (x + 0.5);
        }

        /**
         * Round x into long
         */
        public static long longRound(double x) {
            if (x < 0) {
                return -(long) (-x + 0.5);
            }
            return (long) (x + 0.5);
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

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

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

        public int readInt() {
            int sign = 1;

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

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

            return val;
        }

        public long readLong() {
            int sign = 1;

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

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

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


//package Contest551;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

public class mainF {
    public static Scanner enter = new Scanner(System.in);
    public static PrintWriter out = new PrintWriter(System.out);
    public static long mod=998244353;
    public static long cnk[][]=new long[(int)2e3+2][(int)2e3+2];
    public static long fact[]=new long[2*(int)2e3+2];
    public static long reverse[]=new long[2*(int)2e3+2];
    public static long deg_2[]=new long[(int)2e3+2];
    public static void main(String[] args) {
        long t=System.currentTimeMillis();
        cnk[0][0]=1;
        for (int i = 1; i <cnk.length ; i++) {
            cnk[0][i]=1;
            for (int j = 1; j <=i ; j++) {
                cnk[j][i]=cnk[j-1][i-1]+cnk[j][i-1];
                cnk[j][i]%=mod;
            }
        }
        fact[0]=1;
        deg_2[0]=1;
        for (int i = 1; i <fact.length ; i++) {
            fact[i]=fact[i-1]*i;
            fact[i]%=mod;
        }
        for (int i = 1; i <deg_2.length ; i++) {
            deg_2[i]=deg_2[i-1]*2;
            deg_2[i]%=mod;
        }
        reverse[1]=1;
        for (int i = 3; i <reverse.length ; i+=2) {
            reverse[i]=bin_pow(fact[i],mod-2,mod);
        }
       /* System.out.println(Arrays.toString(reverse));
        System.out.println(fact[5]);
        System.out.println(reverse[5]);*/
        int n=enter.nextInt();
        int k=enter.nextInt();
        long l=enter.nextInt();
        l%=mod;
        long ans=0;
        for (int i = k; i <=n ; i++) {
            long tmp=0;
            for (int s = 0,c=1; s <=n-i ; s++,c*=-1) {
                long a=1;
                a*=cnk[s][n-i]*deg_2[s];
                a%=mod;
                a*=fact[s+i];
                a%=mod;
                a*=fact[s+i];
                a%=mod;
                a*=reverse[2*(s+i)+1];
                a%=mod;
                tmp+=a*c;
                tmp%=mod;
               // System.out.println(reverse[2*(s+i)+1]);
            }
            //System.out.println(tmp);
            /*ans+=cnk[i][n]*deg_2[i]*tmp;
            ans%=mod;*/
            long  b=1;
            b*=tmp*deg_2[i];
            b%=mod;
            //System.out.println(b);
            b*=cnk[i][n];
            b%=mod;
            ans+=b;
            ans%=mod;
        }
        ans*=l;
        ans%=mod;
        System.out.println((ans<0)? (ans+mod) : ans);

      //  System.out.println(System.currentTimeMillis()-t);

    }
    public static long bin_pow(long a,long b, long mod){//a^b %mod
        long ans=1;
        while(b!=0){
            if((b&1)==1) ans*=a;
            a*=a;
            ans%=mod;
            a%=mod;
            b>>=1;
        }
        return ans;
    }
}


//Created by Aminul on 11/17/2020.

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

import static java.lang.Math.*;

public class CF1447F1 {
    public static void main(String[] args) throws Exception {
        Scanner in = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        int n = in.nextInt();
        int[] arr = new int[n + 1];
        int[] freq = new int[101];
        int mostFreq = 0;
        for (int i = 1; i <= n; i++) {
            arr[i] = in.nextInt();
            freq[arr[i]]++;
            if (freq[arr[i]] > freq[mostFreq]) {
                mostFreq = arr[i];
            }
        }

        int res = 0;
        for (int i = 1; i <= 100; i++) {
            if (i != mostFreq) {
                int tmp = maxSumArrayWithZeroSum(n, mostFreq, i, arr);
                res = max(res, tmp);
            }
        }

        pw.println(res);
        pw.close();
    }

    static int maxSumArrayWithZeroSum(int n, int x, int y, int[] arr) {
        int offset = n + 5;
        int[] idx = new int[offset + offset + 10];
        int invalid = -n - n - n;
        Arrays.fill(idx, invalid);
        int sum = 0, res = 0;
        idx[offset + sum] = 0;
        for (int i = 1; i <= n; i++) {
            if (arr[i] == x) sum++;
            else if (arr[i] == y) sum--;
            if (idx[offset + sum] != invalid) res = max(res, i - idx[offset + sum]);
            else idx[offset + sum] = i;
        }
        return res;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.util.Random;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

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

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

    static class DLinearCongruentialGenerator {
        public int log(int x, int y) {
            int ans = 0;
            while (y != 0 && y % x == 0) {
                ans++;
                y /= x;
            }
            return ans;
        }

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int limit = (int) 2e6;
            IntegerMultiWayStack primeFactors = Factorization.factorizeRangePrime(limit);
            int[] cnts = new int[limit + 1];
            int[] times = new int[limit + 1];
            int[] xs = new int[n];

            in.populate(xs);
            Randomized.shuffle(xs);
            Arrays.sort(xs);
            SequenceUtils.reverse(xs);
            boolean[] retain = new boolean[n];
            for (int i = 0; i < n; i++) {
                int x = xs[i];
                if (cnts[x] == 0) {
                    retain[i] = true;
                    cnts[x] = 1;
                    times[x] = 1;
                    continue;
                }

                for (IntegerIterator iterator = primeFactors.iterator(x - 1); iterator.hasNext(); ) {
                    int p = iterator.next();
                    int log = log(p, x - 1);
                    if (cnts[p] < log) {
                        cnts[p] = log;
                        times[p] = 0;
                    }
                    if (cnts[p] == log) {
                        times[p]++;
                    }
                }
            }

            Modular mod = new Modular(1e9 + 7);
            int prod = 1;
            for (int i = 1; i <= limit; i++) {
                for (int j = 0; j < cnts[i]; j++) {
                    prod = mod.mul(prod, i);
                }
            }

            for (int i = 0; i < n; i++) {
                int x = xs[i];
                boolean unique = false;
                if (retain[i]) {
                    if (cnts[x] == 1 && times[x] == 1) {
                        unique = true;
                    }
                } else {
                    for (IntegerIterator iterator = primeFactors.iterator(x - 1); iterator.hasNext(); ) {
                        int p = iterator.next();
                        int log = log(p, x - 1);
                        if (cnts[p] == log && times[p] == 1) {
                            unique = true;
                        }
                    }
                }
                if (!unique) {
                    prod = mod.plus(prod, 1);
                    break;
                }
            }

            out.println(prod);
        }

    }

    static class Modular {
        int m;

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

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

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

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

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

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

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

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

    }

    static class DigitUtils {
        private DigitUtils() {
        }

        public static boolean isMultiplicationOverflow(long a, long b, long limit) {
            if (limit < 0) {
                limit = -limit;
            }
            if (a < 0) {
                a = -a;
            }
            if (b < 0) {
                b = -b;
            }
            if (a == 0 || b == 0) {
                return false;
            }
            //a * b > limit => a > limit / b
            return a > limit / b;
        }

    }

    static class RandomWrapper {
        private Random random;
        public static RandomWrapper INSTANCE = new RandomWrapper(new Random());

        public RandomWrapper() {
            this(new Random());
        }

        public RandomWrapper(Random random) {
            this.random = random;
        }

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

    }

    static class Randomized {
        public static void shuffle(int[] data) {
            shuffle(data, 0, data.length - 1);
        }

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

        public static int nextInt(int l, int r) {
            return RandomWrapper.INSTANCE.nextInt(l, r);
        }

    }

    static class MinimumNumberWithMaximumFactors {
        private static int[] primes = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};

        public static long[] maximumPrimeFactor(long n) {
            long[] ans = new long[2];
            ans[0] = 1;
            for (int i = 0; i < primes.length; i++) {
                if (DigitUtils.isMultiplicationOverflow(ans[0], primes[i], n)) {
                    break;
                }
                ans[0] *= primes[i];
                ans[1]++;
            }
            return ans;
        }

    }

    static class IntegerMultiWayStack {
        private int[] values;
        private int[] next;
        private int[] heads;
        private int alloc;
        private int stackNum;

        public IntegerIterator iterator(final int queue) {
            return new IntegerIterator() {
                int ele = heads[queue];

                public boolean hasNext() {
                    return ele != 0;
                }

                public int next() {
                    int ans = values[ele];
                    ele = next[ele];
                    return ans;
                }
            };
        }

        private void doubleCapacity() {
            int newSize = Math.max(next.length + 10, next.length * 2);
            next = Arrays.copyOf(next, newSize);
            values = Arrays.copyOf(values, newSize);
        }

        public void alloc() {
            alloc++;
            if (alloc >= next.length) {
                doubleCapacity();
            }
            next[alloc] = 0;
        }

        public boolean isEmpty(int qId) {
            return heads[qId] == 0;
        }

        public IntegerMultiWayStack(int qNum, int totalCapacity) {
            values = new int[totalCapacity + 1];
            next = new int[totalCapacity + 1];
            heads = new int[qNum];
            stackNum = qNum;
        }

        public void addLast(int qId, int x) {
            alloc();
            values[alloc] = x;
            next[alloc] = heads[qId];
            heads[qId] = alloc;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < stackNum; i++) {
                if (isEmpty(i)) {
                    continue;
                }
                builder.append(i).append(": ");
                for (IntegerIterator iterator = iterator(i); iterator.hasNext(); ) {
                    builder.append(iterator.next()).append(",");
                }
                if (builder.charAt(builder.length() - 1) == ',') {
                    builder.setLength(builder.length() - 1);
                }
                builder.append('\n');
            }
            return builder.toString();
        }

    }

    static class Factorization {
        public static IntegerMultiWayStack factorizeRangePrime(int n) {
            int maxFactorCnt = (int) MinimumNumberWithMaximumFactors.maximumPrimeFactor(n)[1];
            IntegerMultiWayStack stack = new IntegerMultiWayStack(n + 1, n * maxFactorCnt);
            boolean[] isComp = new boolean[n + 1];
            for (int i = 2; i <= n; i++) {
                if (isComp[i]) {
                    continue;
                }
                for (int j = i; j <= n; j += i) {
                    isComp[j] = true;
                    stack.addLast(j, i);
                }
            }
            return stack;
        }

    }

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

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

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

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

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

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

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

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

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

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

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

    }

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

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

        public static void reverse(int[] data) {
            reverse(data, 0, data.length - 1);
        }

    }

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

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

        public void populate(int[] data) {
            for (int i = 0; i < data.length; i++) {
                data[i] = readInt();
            }
        }

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

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

        public int readInt() {
            int sign = 1;

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

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

            return val;
        }

    }

    static interface IntegerIterator {
        boolean hasNext();

        int next();

    }
}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.NoSuchElementException;

public class C {

  private void solve(FastScanner in, PrintWriter out) {
    int MAX = 50;

    // count[i] := 2^i の数
    int[] count = new int[MAX + 1];

    // garbage[i] := 2^(i+1) 以下の garbage の数
    int[] garbage = new int[MAX + 1];

    int N = in.nextInt();
    for (int i = 0; i < N; i++) {
      long z = in.nextLong();
      if (Long.bitCount(z) == 1) {
        //2べきのものはカウントする
        count[Long.numberOfTrailingZeros(z)]++;
      } else {
        long floor = Long.highestOneBit(z);
        garbage[Long.numberOfTrailingZeros(floor)]++;
      }
    }

    for (int bit = 0; bit < MAX; bit++) {
      if (count[bit] < count[bit + 1]) {
        garbage[bit] += count[bit + 1] - count[bit];
        count[bit + 1] = count[bit];
      }
    }

    ArrayList<Integer> answers = new ArrayList<>();
    for (int ans = 1; ans <= N; ans++) {
      if (count[0] < ans) {
        continue;
      }

      int currentGarbage = 0;
      for (int bit = 0; bit < MAX; bit++) {
        //今建っている整数
        int now = Math.min(count[bit], ans);
        //まだ高さがある整数
        int next = Math.min(count[bit + 1], ans);

        // ここで garbageを吸着できる整数
        int catching = now - next;

        //新たに生まれた garbage
        int newGarbage = Math.max(0, count[bit] - ans);

        currentGarbage += garbage[bit] + newGarbage - catching;
        if (currentGarbage < 0) {
          currentGarbage = 0;
        }
      }

      if (currentGarbage == 0) {
        answers.add(ans);
      }
    }

    if (answers.isEmpty()) {
      out.println(-1);
      return;
    }
    for (int a : answers) {
      out.print(a + " ");
    }
    out.println();
  }

  public static void main(String[] args) {
    PrintWriter out = new PrintWriter(System.out);
    new C().solve(new FastScanner(), out);
    out.close();
  }

  private static class FastScanner {

    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int bufferLength = 0;

    private boolean hasNextByte() {
      if (ptr < bufferLength) {
        return true;
      } else {
        ptr = 0;
        try {
          bufferLength = in.read(buffer);
        } catch (IOException e) {
          e.printStackTrace();
        }
        if (bufferLength <= 0) {
          return false;
        }
      }
      return true;
    }

    private int readByte() {
      if (hasNextByte()) {
        return buffer[ptr++];
      } else {
        return -1;
      }
    }

    private static boolean isPrintableChar(int c) {
      return 33 <= c && c <= 126;
    }

    private void skipUnprintable() {
      while (hasNextByte() && !isPrintableChar(buffer[ptr])) {
        ptr++;
      }
    }

    boolean hasNext() {
      skipUnprintable();
      return hasNextByte();
    }

    public String next() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      StringBuilder sb = new StringBuilder();
      int b = readByte();
      while (isPrintableChar(b)) {
        sb.appendCodePoint(b);
        b = readByte();
      }
      return sb.toString();
    }

    long nextLong() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      long n = 0;
      boolean minus = false;
      int b = readByte();
      if (b == '-') {
        minus = true;
        b = readByte();
      }
      if (b < '0' || '9' < b) {
        throw new NumberFormatException();
      }
      while (true) {
        if ('0' <= b && b <= '9') {
          n *= 10;
          n += b - '0';
        } else if (b == -1 || !isPrintableChar(b)) {
          return minus ? -n : n;
        } else {
          throw new NumberFormatException();
        }
        b = readByte();
      }
    }

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

    double[] nextDoubleArray(int n) {
      double[] array = new double[n];
      for (int i = 0; i < n; i++) {
        array[i] = nextDouble();
      }
      return array;
    }

    double[][] nextDoubleMap(int n, int m) {
      double[][] map = new double[n][];
      for (int i = 0; i < n; i++) {
        map[i] = nextDoubleArray(m);
      }
      return map;
    }

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

    public int[] nextIntArray(int n) {
      int[] array = new int[n];
      for (int i = 0; i < n; i++) {
        array[i] = nextInt();
      }
      return array;
    }

    public long[] nextLongArray(int n) {
      long[] array = new long[n];
      for (int i = 0; i < n; i++) {
        array[i] = nextLong();
      }
      return array;
    }

    public String[] nextStringArray(int n) {
      String[] array = new String[n];
      for (int i = 0; i < n; i++) {
        array[i] = next();
      }
      return array;
    }

    public char[][] nextCharMap(int n) {
      char[][] array = new char[n][];
      for (int i = 0; i < n; i++) {
        array[i] = next().toCharArray();
      }
      return array;
    }

    public int[][] nextIntMap(int n, int m) {
      int[][] map = new int[n][];
      for (int i = 0; i < n; i++) {
        map[i] = nextIntArray(m);
      }
      return map;
    }
  }
}


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

public class C {
  FastScanner in;
  PrintWriter out;

  public void solve() throws IOException {
    int[] powCnt = new int[63];
    int[] other = new int[63];
    long[] pows = new long[63];
    pows[0] = 1L;
    for (int i = 1; i < 63; i++) {
      pows[i] = pows[i - 1] * 2;
    }

    int n = in.nextInt();
    long[] a = new long[n];

    for (int i = 0; i < n; i++) {
      a[i] = in.nextLong();
      boolean isPow = false;
      for (int j = 0; j < 63; j++) {
        if (a[i] == pows[j]) {
          powCnt[j]++;
          isPow = true;
        }
        if (!isPow && j != 0 && a[i] > pows[j - 1] && a[i] < pows[j]) {
          other[j]++;
        }
      }
    }

    int min = Arrays.stream(other).sum();
    int max = powCnt[0];
    boolean exists = false;
    for (int len = min; len <= max; len++) {
      int tails = 0;
      int cur = len;
      for (int i = 0; i < 62; i++) {
        int oldCur = cur;
        if (powCnt[i] < cur) {
          cur = powCnt[i];
        }
        int ended = oldCur - cur;
        if (tails < ended) {
          tails = 0;
        } else {
          tails -= ended;
        }
        tails += powCnt[i] - cur;
        tails += other[i + 1];
      }
      if (tails == 0) {
        out.print(len + " ");
        exists = true;
      }
    }
    if (!exists) {
      out.println(-1);
    } else {
      out.println();
    }
  }

  public void run() {
    try {
      in = new FastScanner(System.in);
      out = new PrintWriter(System.out);
      solve();

      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  class FastScanner {
    BufferedReader br;
    StringTokenizer st;

    FastScanner(InputStream is) {
      br = new BufferedReader(new InputStreamReader(is));
    }

    String next() {
      while (st == null || !st.hasMoreTokens()) {
        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());
    }
  }

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


import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) throws IOException {

        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = sc .nextInt();
        long[] a = new long[n];
        for(int i = 0; i < n; ++i)
            a[i] = sc.nextLong();
        ArrayList<Long> b = new ArrayList<>();
        ArrayList<Long> c = new ArrayList<>();
        ArrayList<Integer> d = new ArrayList<>();
        int idx = 0;
        long curPower = 1;
        boolean possible = true;
        for(long x: a)
            if (x == 1) {
                b.add(1l);
                d.add(1);
            } else if ((x & x - 1) == 0) {
                if (x != curPower) {
                    if (curPower * 2 != x) {
                        possible = false;
                        break;
                    }
                    curPower = x;
                    idx = 0;
                }
                if (idx < b.size() && b.get(idx) * 2 == x) {
                    b.set(idx, x);
                    d.set(idx, d.get(idx) + 1);
                    ++idx;
                }
                else
                    c.add(x);
            } else {
                c.add(x);
            }
        int open = b.size();
        possible &= b.size() >= c.size();
        if(possible) for(int i = c.size() - 1, j = 0; i >= 0; --i, ++j) {
            if(c.get(i) <= 2 * b.get(j)) --open;
            else {
                possible = false;
                break;
            }
        }
        ArrayList<Integer> ans = new ArrayList<>();
        if (possible) {
            ans.add(b.size());
            int free = 0;
            for(int i = b.size() - 1; i >= 0; --i) {
                open--;
                free += d.get(i);
                if (open >= free)
                    ans.add(i);
                else
                    break;
            }
            Collections.reverse(ans);
            for(int x: ans)
                out.print(x + " ");
        } else {
            out.println(-1);
        }
        out.close();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

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

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

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

        public String nextLine() throws IOException {return br.readLine();}

        public boolean ready() throws IOException {return br.ready();}

    }
}


import java.util.Arrays;
import java.util.Scanner;

public class C {
    static int MOD = 1000000007;
    static long MODSQR = MOD * 1L * MOD;

    public static int[][] mul(int[][] a, int[][] b) {
        int[][] result = new int[a.length][b[0].length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                long res = 0;
                for (int k = 0; k < a[0].length; k++) {
                    res = (res + a[i][k] * 1L * b[k][j]);
                    if (res > MODSQR)
                        res %= MOD;
                }
                result[i][j] = (int) (res % MOD);
            }
        }
        return result;
    }

    public static int[][] matpow(int[][] base, long exp) {
        int[][] result = new int[base.length][base.length];
        for (int i = 0; i < base.length; i++)
            result[i][i] = 1;
        while (exp > 0) {
            if ((exp & 1) != 0)
                result = mul(result, base);
            base = mul(base, base);
            exp >>= 1;
        }
        return result;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long n = in.nextLong();
        int k = in.nextInt();
        int[][] C = new int[k + 1][k + 1];
        C[0][0] = 1;
        for (int i = 1; i <= k; i++) {
            C[i][0] = 1;
            for (int j = 1; j <= k; j++)
                C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
        }
        int[][] matrix = new int[2 * k + 3][2 * k + 3];
        for (int i = 0; i <= k; i++) {
            for (int j = 0; j <= i; j++) {
                matrix[i][j] = C[i][j];
                matrix[i][k + j + 1] = C[i][j];
            }
        }
        for (int i = k + 1; i <= 2 * k + 1; i++) {
            int left = i - k - 1;
            for (int j = 0; j <= left; j++) {
                matrix[i][j] = C[left][j];
            }
        }
        matrix[2 * k + 2][2 * k + 2] = 1;
        matrix[2 * k + 2][k] = 1;
        // for (long[] a : matrix)
        // System.out.println(Arrays.toString(a));
        int[][] columnMatrix = new int[2 * k + 3][1];
        for (int i = 0; i < 2 * k + 2; i++)
            columnMatrix[i][0] = 1;
        matrix = matpow(matrix, n);

        columnMatrix = mul(matrix, columnMatrix);
        // for (long[] a : columnMatrix)
        // System.out.println(Arrays.toString(a));
        System.out.println(columnMatrix[2 * k + 2][0]);
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.InputStream;

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

class TaskC {
    private static final int MOD = 1000000007;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        long N = in.nextLong();
        int K = in.nextInt();

        int[][] comb = new int[K + 1][K + 1];
        comb[0][0] = 1;
        for(int i = 1; i <= K; i++) {
            comb[i][0] = comb[i][i] = 1;
            for(int j = 1; j < i; j++) {
                comb[i][j] = comb[i - 1][j - 1] + comb[i - 1][j];
                if(comb[i][j] >= MOD)
                    comb[i][j] -= MOD;
            }
        }

        int[][] A = new int[2 * K + 3][2 * K + 3];
        for(int k = 0; k <= K; k++) {
            for(int i = 0; i <= k; i++)
                A[i][k] = comb[k][k - i];
            for(int i = K + 1; i <= K + 1 + k; i++)
                A[i][k] = (int) (comb[k][k - (i - (K + 1))] * (1L << (k - (i - (K + 1)))) % MOD);
        }
        for(int k = K + 1; k <= 2 * K + 1; k++)
            A[k - (K + 1)][k] = 1;
        for(int i = 0; i <= 2 * K + 1; i++)
            A[i][2 * K + 2] = A[i][K];
        A[2 * K + 2][2 * K + 2] = 1;

        int[][] R = fastPow(A, N - 1);

        long ans = 0;
        for(int i = 0; i <= K + 1; i++) {
            ans += R[i][2 * K + 2];
        }
        ans += R[2 * K + 2][2 * K + 2];
        ans %= MOD;

        out.println(ans);
    }

    private int[][] fastPow(int[][] A, long P) {
        int[][] R = new int[A.length][A.length];
        for(int i = 0; i < R.length; i++)
            R[i][i] = 1;

        while(P > 0) {
            if((P & 1) > 0)
                R = mult(R, A);
            A = mult(A, A);
            P >>= 1;
        }

        return R;
    }

    private int[][] mult(int[][] A, int[][] B) {
        int n = A.length;
        int[][] C = new int[n][n];
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++) {
                long crt = 0;
                for(int k = 0; k < n; k++) {
                    crt += (long)A[i][k] * B[k][j];
                    if(crt > 1e16)
                        crt %= MOD;
                }
                crt %= MOD;
                C[i][j] = (int) crt;
            }
        return C;
    }
}

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

    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 nextInt() {
        return Integer.parseInt(nextString());
    }

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

    public String nextString() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuffer res = new StringBuffer();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isSpaceChar(c));

        return res.toString();
    }

    private boolean isSpaceChar(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    }


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

public class Main {

   void solve(){
       long n=nl();
        int k=ni();
        if(n==1){
            pw.println("1");
            return;
        }
        precompute(k+2);
        sz=k+1+k+1+1;
        long Mat[][]=new long[sz][sz];
        for(int i=0;i<=k;i++){
            Mat[k+1+i][i]=1;
        }
        for(int c=0;c<=k;c++){
            for(int r=0;r<=c;r++){
                Mat[r][k+1+c]=mul(ncr(c,r),pow[c-r],M);
                Mat[k+1+r][k+1+c]=ncr(c,r);
            }
        }
        for(int i=0;i<=2*k+1;i++) Mat[i][2*k+2]=Mat[i][2*k+1];
        Mat[sz-1][sz-1]=1;

        Mat=pow(Mat,n-2);
        long arr[]=new long[sz];
        for(int i=0;i<=k;i++) arr[i]=1;
        for(int i=k+1;i<=2*k+1;i++) arr[i]=pow[i-k];
        arr[sz-1]=1;
        arr[sz-1]=add(arr[sz-1],pow[k+1],M);
//        for(int i=0;i<sz;i++){
//            for(int j=0;j<sz;j++) pw.print(Mat[i][j]+" ");
//            pw.println("");
//        }
        long ans=0;
        for(int i=0;i<sz;i++){
            ans=add(ans,mul(arr[i],Mat[i][sz-1],M),M);
        }
        pw.println(ans);

    }
    int sz;
    long [][] pow(long A[][],long x){
        if(x==0){
            long C[][]=new long[sz][sz];
            for(int i=0;i<sz;i++) C[i][i]=1;
            return C;
        }else if(x==1){
            return A;
        }
        long C[][]=pow(A,x/2);
        C=mul(C,C);
        if((x&1)>0) return mul(A,C);
        return C;

    }
    long [][] mul(long A[][],long B[][]){
        long C[][]=new long[sz][sz];
        for(int i=0;i<sz;i++){
            for(int j=0;j<sz;j++){
                for(int k=0;k<sz;k++){
                    //C[i][j]=(C[i][j]+(A[i][k]%M * B[k][j]%M)%M)%M;
                    C[i][j]=add(C[i][j],mul(A[i][k],B[k][j],M),M);
                }
            }
        }
        return C;
    }

    long ncr(int n,int r) {
        long ans = fact[n];
        ans=mul(ans,inv[n-r],M);
        ans=mul(ans,inv[r],M);
        return ans;
    }
    long fact[];
    long inv[];
    long pow[];
    void precompute(int n){
       fact=new long[n+1];
       inv=new long[n+1];
       pow=new long[n+1];
       pow[0]=1;
       fact[0]=1;
       for(int i=1;i<=n;i++){
           pow[i]=(pow[i-1]*2)%M;
           fact[i]=(fact[i-1]*i)%M;
       }
       inv[n]=modInverse(fact[n],M);
        for(int i=n-1;i>=0;i--) inv[i]=(inv[i+1]*(i+1))%M;

    }
    long add(long x,long y,long M){
        x+=y;
        if(x>=M) x-=M;
        return x;
    }
    long sub(long x,long y,long M){
        x-=y;
        if(x<0) x+=M;
        return x;
    }
    long mul(long x,long y,long M){
        x*=y;
        if(x>=M) x%=M;
        return x;
    }
    long modpow(long a, long b,long M)
    {
        long r=1;
        while(b>0)
        {
            if((b&1)>0) r=mul(r,a,M);
            a=mul(a,a,M);
            b>>=1;
        }
        return r;
    }

    long modInverse(long A, long M)
    {

        return modpow(A,M-2,M);
    }

    long M= (long)1e9+7;
    InputStream is;
    PrintWriter pw;
    String INPUT = "";
    void run() throws Exception {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        pw = new PrintWriter(System.out);
        long s = System.currentTimeMillis();
        solve();
        pw.flush();
        if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");

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

    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if(lenbuf == -1)throw new InputMismatchException();
        if(ptrbuf >= lenbuf){
            ptrbuf = 0;
            try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
            if(lenbuf <= 0)return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
    private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

    private double nd() { return Double.parseDouble(ns()); }
    private char nc() { return (char)skip(); }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while(p < n && !(isSpaceChar(b))){
            buf[p++] = (char)b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for(int i = 0;i < n;i++)map[i] = ns(m);
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for(int i = 0;i < n;i++)a[i] = ni();
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
    private void tr(Object... o) { if(INPUT.length() > 0)System.out.println(Arrays.deepToString(o)); }

}