import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Array; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; import java.util.Queue; import java.util.Random; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.DoubleUnaryOperator; import java.util.function.Function; import java.util.function.IntBinaryOperator; import java.util.function.IntFunction; import java.util.function.IntToDoubleFunction; import java.util.function.IntToLongFunction; import java.util.function.IntUnaryOperator; import java.util.function.LongBinaryOperator; import java.util.function.LongToDoubleFunction; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.function.ToIntFunction; import java.util.random.RandomGenerator; import java.util.stream.IntStream; import java.util.stream.Stream; class FastScanner { private static FastScanner instance = null; private final InputStream in = System.in; private final byte[] buffer = new byte[1024]; private int ptr = 0; private int buflen = 0; private FastScanner() { } public static FastScanner getInstance() { if (instance == null) { instance = new FastScanner(); } return instance; } private boolean hasNextByte() { if (ptr < buflen) { return true; } ptr = 0; try { buflen = in.read(buffer); } catch (IOException e) { e.printStackTrace(); } return buflen > 0; } private int readByte() { if (hasNextByte()) { return buffer[ptr++]; } else { return -1; } } private boolean isPrintableChar(int c) { return (33 <= c) && (c <= 126); } public boolean hasNext() { while (hasNextByte() && (!isPrintableChar(buffer[ptr]))) { ptr++; } return hasNextByte(); } public long nextLong() { if (!hasNext()) { throw new NoSuchElementException(); } long n = 0; boolean minus = false; int b = readByte(); if (b == '-') { minus = true; b = readByte(); } while ((b >= '0') && (b <= '9')) { // n = n * 10 + (b - '0'); n = ((n << 1) + (n << 3)) + (b - '0'); b = readByte(); } return minus ? -n : n; } public int nextInt() { return ((int) (nextLong())); } } class MergeFiles {} class Zn { final long mod; public Zn(long mod) { this.mod = mod; } /** * * * 剰余を取り、0以上mod未満の値を返す。 * * @param a * @return */ public long reduce(long a) { a %= mod; if (a < 0) { a += mod; } return a; } } class ArrayUtils { public static void swap(long[] A, long[] B) { if (A.length != B.length) { throw new AssertionError(); } for (int i = 0; i < A.length; i++) { long tmp = A[i]; A[i] = B[i]; B[i] = tmp; } } } class MyPrintWriter extends PrintWriter { private static MyPrintWriter instance = null; private MyPrintWriter() { super(System.out); } public static MyPrintWriter getInstance() { if (instance == null) { instance = new MyPrintWriter(); } return instance; } public void println(boolean[][] a) { for (int i = 0; i < a.length; i++) { println(a[i], " "); } } public void println(boolean[] a, String separator) { for (int i = 0; i < a.length; ++i) { super.print((a[i] ? 1 : 0) + (i == (a.length - 1) ? "\n" : separator)); } } } class Fp extends Zn { public Fp(long mod) { super(mod); } long[] inv = new long[0]; public long inv(long n) { if (n < 0) { n = reduce(n); } return n < inv.length ? inv[((int) (n))] : MathUtils.modInv(n, mod); } public long combNaive(long n, long k) { if ((k < 0) || ((n - k) < 0)) { return 0; } k = Math.min(k, n - k); long ret = 1; for (int i = 0; i < k; i++) { ret = (ret * (n - i)) % mod; ret = (ret * inv(i + 1)) % mod; } return ret; } public long pow(long a, long n) { return MathUtils.modPow(a, n, mod); } } class MathUtils { public static long modPow(long a, long n, long mod) { if (n < 0) { long inv = MathUtils.modInv(a, mod); return MathUtils.modPow(inv, -n, mod); } if (n == 0) { return 1; } return (MathUtils.modPow((a * a) % mod, n / 2, mod) * ((n % 2) == 1 ? a : 1)) % mod; } /** * 拡張ユークリッドの互除法で逆元を求める。 * * @param a * @param mod * @return */ public static long modInv(long a, long mod) { a = ((a % mod) + mod) % mod; long[] f0 = new long[]{ 1, 0, mod }; long[] f1 = new long[]{ 0, 1, a }; while (f1[2] != 0) { long q = f0[2] / f1[2]; for (int i = 0; i < 3; i++) { f0[i] -= q * f1[i]; } ArrayUtils.swap(f0, f1); } return f0[1] < 0 ? mod + f0[1] : f0[1]; } } public class Main implements Runnable { public static void main(String[] args) throws IOException { Thread.setDefaultUncaughtExceptionHandler((t, e) -> System.exit(1)); // Runtime runtime = Runtime.getRuntime(); // new Thread(null, new Main(), "MainThreadWithLargeStack", (1024 * 1024) * 1024).start(); // new Main().test(); // new Main().gen(); new Main().run(); // long usedMemory = runtime.totalMemory() - runtime.freeMemory(); // System.err.printf("使用メモリ: %.2f MB%n", usedMemory / 1024.0 / 1024.0); MyPrintWriter.getInstance().flush(); } @Override public void run() { FastScanner sc = FastScanner.getInstance(); MyPrintWriter pw = MyPrintWriter.getInstance(); long mod = 998244353; int N = sc.nextInt(); int M = sc.nextInt(); Fp fp = new Fp(mod); long q = fp.pow(2, N) - 1; q = fp.reduce(q); long ans = fp.combNaive(q, M); long n = fp.pow(2, N - 1);// (2^n)-1で2^(n-1)-1がすでに占有済み。残り2^(n-1) long x = (fp.combNaive(n, M) * fp.inv(n)) % mod; x = (x * q) % mod; ans -= x * M; ans = fp.reduce(ans); pw.println(ans); } } // --- Original Code --- // package template; // // import java.io.IOException; // import java.nio.file.Files; // import java.nio.file.Path; // import java.util.Arrays; // import java.util.List; // import java.util.Random; // // import library.tools.FastScanner; // import library.tools.MergeFiles; // import library.tools.MyPrintWriter; // import library.util.Fp; // import library.util.MathUtils; // import library.util.polynomial.PolynomialFp; // // public class Main implements Runnable { // // public static void main(String[] args) throws IOException { // // Runtime runtime = Runtime.getRuntime(); // // new Thread(null, new Main(), "MainThreadWithLargeStack", (1024 * 1024) * 1024).start(); // // new Main().test(); // // new Main().gen(); // new Main().run(); // // long usedMemory = runtime.totalMemory() - runtime.freeMemory(); // // System.err.printf("使用メモリ: %.2f MB%n", usedMemory / 1024.0 / 1024.0); // MyPrintWriter.getInstance().flush(); // MergeFiles.export(); // } // // @Override // public void run() { // FastScanner sc = FastScanner.getInstance(); // MyPrintWriter pw = MyPrintWriter.getInstance(); // // long mod = 998244353; // int N = sc.nextInt(); // int M = sc.nextInt(); // Fp fp = new Fp(mod); // long q = fp.pow(2, N) - 1; // q = fp.reduce(q); // long ans = fp.combNaive(q, M); // long n = fp.pow(2, N - 1);// (2^n)-1で2^(n-1)-1がすでに占有済み。残り2^(n-1) // long x = fp.combNaive(n, M) * fp.inv(n) % mod; // x = (x * q) % mod; // ans -= x * M; // ans = fp.reduce(ans); // pw.println(ans); // } // // void abc() { // Random rnd = new Random(); // try { // List candidates = Files.readAllLines(Path.of("problems.txt")).stream() // .filter(line -> !line.contains("o")).map(line -> line.split("\\s+")[0]).toList(); // // String problem = candidates.get(rnd.nextInt(candidates.size())); // System.out.println(problem); // // } catch (IOException e) { // e.printStackTrace(); // } // } // // void tr(Object... objects) { // System.out.println(Arrays.deepToString(objects)); // } // } //