//package codeforces.br23;

import java.io.*;

/**
 * User: Kandy
 * Date: 12.07.2010
 * Time: 21:51:52
 */
public class ProblemA {
    public void solve() {
        boolean oj = true;

        try {
            Reader reader = oj ? new InputStreamReader(System.in) : new FileReader("A.in");
            Writer writer = oj ? new OutputStreamWriter(System.out) : new FileWriter("A.out");
            BufferedReader br = new BufferedReader(reader);
            StreamTokenizer st = new StreamTokenizer(reader);
            PrintWriter out = new PrintWriter(writer);

            String s = br.readLine();
            int n = s.length();

            int max = 0;
            for (int i = 0; i < n; i++)
                for (int j = i; j < n; j++) {
                    int len = j - i + 1;
                    int count = 0;
                    for (int k = 0; k < n - len + 1; k++) {
                        boolean eq = true;
                        for(int l = 0; l < len;l++) {
                            if (s.charAt(i + l) != s.charAt(k + l)) {
                                eq = false;
                                break;
                            }
                        }
                        if (eq) {
                            count++;
                        }
                    }
                    if (count >= 2 && len > max) {
                        max = len;
                    }
                }

            out.printf("%d", max);

            br.close();
            out.close();
            reader.close();
            writer.close();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        finally {
        }
    }

    public static void main(String[] args) {
        ProblemA f = new ProblemA();
        f.solve();
    }

    private class MyTokenizer {
        private String s;
        private int cur;

        public MyTokenizer(String s) {
            this.s = s;
            cur = 0;
        }

        public void skip() {
            while (cur < s.length() && (s.charAt(cur) == ' ' || s.charAt(cur) == '\n')) {
                cur++;
            }
        }

        public double getNum() {
            skip();
            String snum = "";
            while (cur < s.length() && (s.charAt(cur) >= '0' && s.charAt(cur) <= '9' || s.charAt(cur) == '.' || s.charAt(cur) == '-')) {
                snum += s.charAt(cur);
                cur++;
            }
            return Double.valueOf(snum);
        }

        public String getString() {
            skip();
            String s2 = "";
            while (cur < s.length() && (((s.charAt(cur) >= 'a' && s.charAt(cur) <= 'z')) || ((s.charAt(cur) >= 'A' && s.charAt(cur) <= 'Z')))) {
                s2 += s.charAt(cur);
                cur++;
            }
            return s2;
        }

        public char getCurrentChar() throws Exception {
            if (cur < s.length())
                return s.charAt(cur);
            else
                throw new Exception("Current character out of string length");
        }

        public void moveNextChar() {
            if (cur < s.length())
                cur++;
        }

        public boolean isFinished() {
            return cur >= s.length();
        }
    }
}


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import com.sun.org.apache.xalan.internal.xsltc.dom.BitArray;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.BitSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author abdelrahman
 */
public class p1 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new p1().run();

    }

    private void run() {
        try {
            // TODO code application logic here
            Scanner scanner = new Scanner(System.in);
            String in = scanner.next();

            Hashtable<String, Boolean> tmp = new Hashtable<String, Boolean>();
            int sol = 0;
            for (int i = 0; i < in.length(); i++) {
                for (int j = i + 1; j <= in.length(); j++) {
                    String str = in.substring(i, j);
                    if (tmp.containsKey(str)) {
                        if (tmp.get(str)) {
                            if(str.length() > sol)  sol=str.length();
                            boolean tmp1 = tmp.remove(str);
                            tmp.put(str, false);
                        }
                    } else {
                        tmp.put(str, Boolean.TRUE);
                    }
                }

            }
            System.out.println(sol);
        } catch (Exception ex) {
        }
    }

}


import java.io.BufferedReader;
import static java.lang.Math.*;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class CFC23A implements Runnable {
	BufferedReader in;
	PrintWriter out;
	StringTokenizer tok;

	public static void main(String[] args) {
		new Thread(new CFC23A()).start();
	}

	void solve() throws IOException {
		int res = 0;
		String str = nextToken();
		for(int i = 0; i < str.length(); ++i)
			for(int j = i + 1; j <= str.length(); ++j)
				if(isOk(str.substring(i, j), str))
					res = max(res, j - i);
		out.println(res);
	}

	private boolean isOk(String substring, String str) {
		int from = 0, kol = 0;
		while(str.indexOf(substring, from) != -1 && kol < 2) {
			++kol;
			from = str.indexOf(substring, from) + 1;
		}
		return kol >= 2;
	}

	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			// in = new BufferedReader(new FileReader(new File("input.txt")));
			out = new PrintWriter(System.out);
			//out = new PrintWriter(new File("output.txt"));
			solve();
			out.flush();
			out.close();
			in.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	String nextLine() throws IOException {
		tok = null;
		return in.readLine();
	}

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

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

	String nextToken() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}
}


/**
 * Mx 04:06:52 ص 14/01/2014
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder line = new StringBuilder(reader.readLine());
        int length = 0;
        for (int head = 0; head < line.length(); head++) {
            for (int tail = line.length() - 1; tail > head; tail--) {
                String subString = line.substring(head, tail);
                if(line.indexOf(subString,head+1)>-1){
                    length = Math.max(subString.length(), length);
                }
            }
        }
        System.out.println(length);
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.*;
import java.util.*;
import java.lang.*;

public class A {

	private BufferedReader in;
	private StringTokenizer st;

	void solve() throws IOException{

		int len = 0;
		String x = next();
		HashSet<String> h = new HashSet<String>();
		for (int i = 0; i < x.length(); i++) {
			for (int j = i+1; j <= x.length(); j++) {
				String y = x.substring(i,j);
				if(h.contains(y)){
					if(y.length()>len) len = y.length();
				}
				else h.add(y);
			}
		}
		System.out.println(len);

	}
	A() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		eat("");
		solve();
	}

	private void eat(String str) {
		st = new StringTokenizer(str);
	}

	String next() throws IOException {
		while (!st.hasMoreTokens()) {
			String line = in.readLine();
			if (line == null) {
				return null;
			}
			eat(line);
		}
		return st.nextToken();
	}

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

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

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

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

		new A();
	}

}


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

public class Main{

    private static int[] T;

    public static void main(String[] args){

        Scanner in = new Scanner(System.in);
        char[] input =  in.nextLine().toCharArray();
        int length = input.length;
        int max = 0;
        for(int i=0; i<length; i++){
            char[] subString = Arrays.copyOfRange(input, 1, input.length);
            int temp = solve(input, subString);
            if(temp > max) max = temp;
            input = Arrays.copyOfRange(input, 1, input.length);
        }
        System.out.println(max);

    }

    private static int solve(char[] P, char[] S) {

        T = new int[P.length+1];

        preKmp(P, P.length, T);
        int max = 0;

        int i = 0, j = 0;
        while (j < S.length) {
            while (i > -1 && (P[i] != S[j]))
                i = T[i];
            i++;
            j++;
            if ( i > max) max = i;
            if (i >= P.length) {
                i = T[i];
            }
        }

        return max;

    }

    private static void preKmp(char[] x, int m, int[] kmpNext) {
           int i = 0, j = kmpNext[0] = -1;

           while (i < m-1) {
              while (j > -1 && x[i] != x[j])
                 j = kmpNext[j];
              i++;
              j++;
              if (x[i] == x[j])
                 kmpNext[i] = kmpNext[j];
              else
                 kmpNext[i] = j;
           }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
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;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        EPhoenixAndComputers solver = new EPhoenixAndComputers();
        solver.solve(1, in, out);
        out.close();
    }

    static class EPhoenixAndComputers {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt(), m = in.nextInt();
            ModInt mod = new ModInt(m);
            int[] factorial = new int[n + 1];
            int[][] binomial = new int[n + 1][n + 1];
            int[] two = new int[n + 1];
            for (int i = 0; i <= n; i++) {
                binomial[i][0] = 1;
                for (int j = 1; j <= i; j++)
                    binomial[i][j] = mod.add(binomial[i - 1][j], binomial[i - 1][j - 1]);
                factorial[i] = i == 0 ? 1 : mod.multiply(factorial[i - 1], i);
                two[i] = i == 0 ? 1 : mod.multiply(2, two[i - 1]);
            }
            int[][] dp = new int[n + 1][n + 1];
            dp[0][0] = 1;
            int answer = 0;
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= i; j++) {
                    for (int x = 1; x <= i; x++) {
                        dp[i][j] = mod.add(dp[i][j],
                                mod.multiply(binomial[i][x], mod.multiply(two[x - 1], dp[i - x][j - 1])));
                    }
                }
            }
            for (int k = 0; k < n; k++) {
                answer = mod.add(answer, dp[n - k][k + 1]);
            }
            out.println(answer);
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void println(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
            writer.print('\n');
        }

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

    }

    static class ModInt {
        int modulo;

        public ModInt(int m) {
            modulo = m;
        }

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

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

    }

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

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


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

public class CF1515E{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int md = sc.nextInt();
		int k = (n + 1) / 2;
		int[][] dp = new int[k + 1][n + 1]; dp[0][0] = 1;
		for (int h = 1; h <= k; h++)
			for (int l = h; l <= n - h + 1; l++)
				dp[h][l] = (int) ((dp[h][l - 1] * 2L + dp[h - 1][l - 1]) * h % md);
		int ans = 0;
		for (int h = 1; h <= k; h++)
			ans = (ans + dp[h][n - h + 1]) % md;
		System.out.println(ans);
	}
}


import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), md = sc.nextInt();
        int k = (n + 1) / 2;int ans = 0;
        int[][] dp = new int[k + 1][n + 1];dp[0][0] = 1;
        for (int h = 1; h <= k; h++)
            for (int l = h; l <= n - h + 1; l++)
                dp[h][l] = (int) ((dp[h][l - 1] * 2L + dp[h - 1][l - 1]) * h % md);
        for (int h = 1; h <= k; h++)
            ans = (ans + dp[h][n - h + 1]) % md;
        System.out.println(ans);
    }
}


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

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 1e9 + 10;
    static final long OO = (long) 1e18 + 10;
    static final int MOD = (int) 1e9 + 7;

    static int M;
    static long[] f, fi, two;

    static long pow(long a, long b) {
        long res = 1;
        while (b != 0) {
            if ((b & 1) == 1)
                res = (res * a) % M;
            a = (a * a) % M;
            b >>= 1;
        }
        return res;
    }

    static long C(int n, int k) {
        return f[n] * fi[k] % M * fi[n - k] % M;
    }

    static void prepare(int n) {
        f = new long[n];
        f[0] = 1;
        for (int i = 1; i < n; i++) {
            f[i] = (f[i - 1] * i) % M;
        }
        fi = new long[n];
        for (int i = 0; i < n; i++) {
            fi[i] = pow(f[i], M - 2);
        }
        two = new long[n];
        two[0] = 1;
        for (int i = 1; i < n; i++) {
            two[i] = (two[i - 1] * 2) % M;
        }
    }

    static void solve() {
        int n = in.nextInt();
        M = in.nextInt();
        prepare(n + 10);
        long[][] dp = new long[n + 1][n];
        for (int i = 1; i <= n; i++) {
            dp[i][1] = two[i - 1];
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 2; j < n; j++) {
                for (int k = 1; k <= i - 2; k++) {
                    if (k < j - 2)
                        continue;
                    int len = i - k - 1;
                    dp[i][j] = (dp[i][j] + dp[k][j - 1] * two[len - 1] % M * C(k - (j - 2) + len, len) % M) % M;
                }
            }
        }
        long ans = 0;
        for (int j = 1; j < n; j++) {
            ans = (ans + dp[n][j]) % M;
        }
        out.println(ans);

    }

    public static void main(String[] args) {
        in = new FastReader();
        out = new PrintWriter(System.out);

        int t = 1;
//        t = in.nextInt();
        while (t-- > 0) {
            solve();
        }

        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader() {
            this(System.in);
        }
        FastReader(String file) throws FileNotFoundException {
            this(new FileInputStream(file));
        }
        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }
        String nextLine() {
            String line;
            try {
                line = br.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return line;
        }
    }
}


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

/**
    @author KhanhNguyenn
 */

public class C{
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.solve(in, out);
        out.close();
    }
    // main solver
    // sub-problem: 2 orders to merge together x1,x2,..,xn and y1,y2,..,ym
    // Dựa vào bài toán chia kẹp Euler, ta chứng minh dc số cách merge là
    // (m+n)C(m-1)=(m+n)C(n+1)
    static class Task{
        int M;
        public void solve(InputReader in, PrintWriter out) {
            int n= in.nextInt(); M= in.nextInt();
            if(n<=1){
                out.println(n);
                return;
            }
            int[] pow2= new int[n+1];
            pow2[0]=1;
            for(int i=1;i<=n;i++) pow2[i]=mul(2,pow2[i-1]);

            // calculate nCk
            // nCk= (n-1)C(k-1)+ (n-1)Ck
            int[][] Ckn= new int[n+1][n+1];
            for(int i=0;i<=n;i++){
                Ckn[i][i]=1; Ckn[0][i]=1;
                for(int j=i-1;j>=1;j--){
                    Ckn[j][i]= add(Ckn[j-1][i-1],Ckn[j][i-1]);
                }
            }

            int ans=0;
            int[][] dp= new int[n+1][n+1];
            dp[1][1]=1;
            //dp[i][j]: number of ways to turn on first i , using j manually
            for(int i=2;i<=n;i++){
                dp[i][i]= pow2[i-1];
                for(int j=1;j<=i-1;j++){
                    for(int k=1;k<=j;k++){
                            dp[i][j]= add(dp[i][j],mul(mul(pow2[k-1],dp[i-k-1][j-k]),Ckn[k][j]));
                    }
                }
            }
            for(int i=0;i<=n;i++) ans= add(ans,dp[n][i]);
            out.println(ans);
        }

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

        public int mul(int a, int b){
            long res= (long)a*(long)b;
            res %=M;
            return (int)res;
        }

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

        // @Override
        // public int compareTo(Pair o) {
        //     if (this.x > o.x){
        //         return 1;
        //     }
        //     else if (this.x < o.x){
        //         return -1;
        //     }
        //     else{
        //         return Integer.compare(this.y, o.y);
        //     }
        // }
    }
    // fast input reader class;
    static class InputReader {
        BufferedReader br;
        StringTokenizer st;

        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
        }

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

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }
        public double nextDouble(){
            return Double.parseDouble(nextToken());
        }
        public long nextLong(){
            return Long.parseLong(nextToken());
        }
    }
}


import java.util.*;
import java.lang.*;
// StringBuilder uses java.lang

public class mC {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        StringBuilder st = new StringBuilder();
        int t = 1;
        for (int test = 0; test < t; test++) {
            int n = sc.nextInt();
            int MOD = sc.nextInt();

            long[] factorial = new long[1000];
            long[] powerOfTwo = new long[1000];
            factorial[0]=1;
            powerOfTwo[0]=1;
            for (int i=1;i<1000;i++) {
                factorial[i]=i*factorial[i-1];
                factorial[i] %= MOD;
                powerOfTwo[i]=2*powerOfTwo[i-1];
                if (powerOfTwo[i]>=MOD) {
                    powerOfTwo[i]-=MOD;
                }
            }
            long[] oneOverFactorial = new long[500];
            oneOverFactorial[0]=1;
            oneOverFactorial[1]=1;
            for (int i=2;i<450;i++) {
                oneOverFactorial[i] = fastPow(factorial[i],MOD-2,MOD);
            }
            long dp[][] = new long[n+3][n+3]; // first value number of computers considered
                                // second value number of computers manually on

            dp[1][1]=1;
            for (int i=2;i<=n;i++) { // from left to right, over first i computers
                dp[i][i]=powerOfTwo[i-1];
                for (int j=1;j<i-1;j++) { // number of computers turned on manually
                    for (int k=1;k<=j;k++) {
                        // want to add dp[j][k]*factorial[k+(i-j-1)]*oneOverFactorial[k]*oneOverFactorial[i-j-1]*powerOfTwo[i-j-2]
                        long add = dp[j][k]*factorial[k+(i-j-1)];
                        add %= MOD;
                        add *= oneOverFactorial[k];
                        add %= MOD;
                        add *= oneOverFactorial[i-j-1];
                        add %= MOD;
                        add *= powerOfTwo[i-j-2];
                        add %= MOD;
                        dp[i][k+(i-j-1)]+=add;
                        dp[i][k+(i-j-1)]%=MOD;
                    }
                }
            }
            long ans = 0;
            for (int i=1;i<=n;i++) {
                ans+=dp[n][i];
            }
            ans %= MOD;
            System.out.println(ans);
        }

        //System.out.print(st.toString());
    }

    public static int goodLeft(int n, int[] p) { // i.e. ... 4 5 6
        int begin = 0;
        for (int i=0;i<n;i++) {
            if (n-i==p[n-i-1]) {
                begin++;
            } else {
                break;
            }
        }
        return begin;
    }
    public static int goodRight(int n, int[] p) { // i.e. 6 5 4 ...
        int end = 0;
        for (int i=n-1;i>=0;i--) {
            if (i==p[i]) {
                end++;
            } else {
                break;
            }
        }
        return end;
    }
    public static int findNthInArray(int[] arr,int val,int start,int o) {
        if (o==0) {
            return start-1;
        } else if (arr[start] == val) {
            return findNthInArray(arr,val,start+1,o-1);
        } else {
            return findNthInArray(arr,val,start+1,o);
        }
    }
    public static ArrayList<Integer> dfs(int at,ArrayList<Integer> went,ArrayList<ArrayList<Integer>> connect) {
        for (int i=0;i<connect.get(at).size();i++) {
            if (!(went.contains(connect.get(at).get(i)))) {
                went.add(connect.get(at).get(i));
                went=dfs(connect.get(at).get(i),went,connect);
            }
        }
        return went;
    } public static int[] bfs (int at, int[] went, ArrayList<ArrayList<Integer>> queue, int numNodes, ArrayList<ArrayList<Integer>> connect) {
        if (went[at]==0) {
            went[at]=queue.get(numNodes).get(1);
            for (int i=0;i<connect.get(at).size();i++) {
                if (went[connect.get(at).get(i)]==0) {
                    ArrayList<Integer> temp = new ArrayList<>();
                    temp.add(connect.get(at).get(i));
                    temp.add(queue.get(numNodes).get(1)+1);
                    queue.add(temp);
                }
            }

        }
        if (queue.size()==numNodes+1) {
            return went;
        } else {
            return bfs(queue.get(numNodes+1).get(0),went, queue, numNodes+1, connect);
        }
    }
    public static long fastPow(long base,long exp,long mod) {
        if (exp==0) {
            return 1;
        } else {
            if (exp % 2 == 1) {
                long z = fastPow(base,(exp-1)/2,mod);
                return ((((z*base) % mod) * z) % mod);
            } else {
                long z = fastPow(base,exp/2,mod);
                return ((z*z) % mod);
            }
        }
    }
    public static int fastPow(int base,long exp) {
        if (exp==0) {
            return 1;
        } else {
            if (exp % 2 == 1) {
                int z = fastPow(base,(exp-1)/2);
                return ((((z*base)) * z));
            } else {
                int z = fastPow(base,exp/2);
                return ((z*z));
            }
        }
    }
    public static int firstLarger(long val,ArrayList<Long> ok,int left,int right) {

        if (ok.get(right)<=val) {
            return -1;
        }
        if (left==right) {
            return left;
        } else if (left+1==right) {
            if (val<ok.get(left)) {
                return left;
            } else {
                return right;
            }
        } else {
            int mid = (left+right)/2;
            if (ok.get(mid)>val) {
                return firstLarger(val,ok,left,mid);
            } else {
                return firstLarger(val,ok,mid+1,right);
            }
        }
    }
    public static int binSearchArr(long val,ArrayList<Integer> ok,long[] arr,int left,int right) {

        if (arr[ok.get(right)]<=val) {
            return -1;
        }
        if (left==right) {
            return left;
        } else if (left+1==right) {
            if (val<arr[ok.get(left)]) {
                return left;
            } else {
                return right;
            }
        } else {
            int mid = (left+right)/2;
            if (arr[ok.get(mid)]>val) {
                return binSearchArr(val,ok,arr,left,mid);
            } else {
                return binSearchArr(val,ok,arr,mid+1,right);
            }
        }
    }
    public static long gcd(long a, long b) {
        if (b>a) {
            return gcd(b,a);
        }
        if (b==0) {
            return a;
        }
        if (a%b==0) {
            return b;
        } else {
            return gcd(b,a%b);
        }
    }
}


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

    static class TaskE {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.nextInt();
            int MOD = in.nextInt();

            int[][] C = new int[n + 1][n + 1];
            C[0][0] = 1;
            for (int i = 1; i < C.length; i++) {
                C[i][0] = 1;
                for (int j = 1; j < C.length; j++) {
                    C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
                    if (C[i][j] >= MOD) {
                        C[i][j] -= MOD;
                    }
                }
            }

            int[] p2 = new int[n + 1];
            p2[0] = 1;
            for (int i = 1; i < p2.length; i++) {
                p2[i] = 2 * p2[i - 1] % MOD;
            }

            int[][] d = new int[n + 1][n + 1];
            d[0][0] = 1;
            // Total.
            for (int i = 1; i <= n; i++) {
                // Switched on manually.
                for (int j = 1; j <= i; j++) {
                    // Switched on manually in the first block.
                    for (int t = 1; t <= j; t++) {
                        if (t == i - 1) {
                            continue;
                        }
                        d[i][j] = (int) ((d[i][j] + (long) C[j][t] * p2[t - 1] % MOD * d[i - t - (i == t ? 0 : 1)][j - t]) % MOD);
                    }
                }
            }

            int ans = 0;
            for (int k = 1; k <= n; k++) {
                ans += d[n][k];
                if (ans >= MOD) {
                    ans -= 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 next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

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

    }
}


//https://github.com/EgorKulikov/yaal/tree/master/lib/main/net/egork

import java.util.*;
import java.io.*;
public class B{
    static PrintWriter out;
    static InputReader in;
    public static void main(String args[]){
        out = new PrintWriter(System.out);
        in = new InputReader();
        new B();
        out.flush(); out.close();
    }
    B(){
        solve();
    }
    class pair{
        int F, S;
        pair(int a, int b){
            F = a; S = b;
        }
    }
    void solve(){
        int n = in.nextInt(), mod = in.nextInt();
        long dp[][] = new long[n + 1][n + 1];
        long ncr[][] = new long[810][410];
        ncr[0][0] = 1;
        for(int i = 1; i < 810; i++){
            for(int j = 0; j < 410; j++){
                ncr[i][j] = (ncr[i - 1][j] + (j > 0 ? ncr[i - 1][j - 1] : 0)) % mod;
            }
        }
        for(int i = 1; i <= n; i++)dp[i][i] = 1;
        for(int i = 1; i < n; i++){
            for(int j = 1; j + i <= n; j++){
                int end = i + j;
                dp[j][end] = (dp[j + 1][end] + dp[j][end - 1]) % mod;
            }
        }
        long value[] = new long[n + 1];
        for(int i = 1; i <= n; i++){
            value[i] = dp[1][i];
        }
        long fdp[][] = new long[n + 2][n + 2];
        fdp[0][0] = 1;
        long ans = 0;
        for(int b = 1; b <= (n + 1) / 2; b++){
            for(int i = 1; i <= n; i++){
                for(int k = Math.max(0, b - 2); k < i; k++){
                    fdp[i + 1][b] = (fdp[i + 1][b] + fdp[k][b - 1] * value[i - k] % mod * ncr[k - b + 2 + i - k - 1][i - k] % mod) % mod;
                }
            }
            ans = (ans + fdp[n + 1][b]) % mod;
        }
        out.print(ans);
    }
    public static class InputReader{
        BufferedReader br;
        StringTokenizer st;
        InputReader(){
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        public int nextInt(){
            return Integer.parseInt(next());
        }
        public long nextLong(){
            return Long.parseLong(next());
        }
        public double nextDouble(){
            return Double.parseDouble(next());
        }
        public String next(){
            while(st == null || !st.hasMoreTokens()){
                try{
                    st = new StringTokenizer(br.readLine());
                }catch(IOException e){}
            }
            return st.nextToken();
        }
    }
}


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

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

    FastReader in = new FastReader();
    PrintWriter out = new PrintWriter(System.out);
    void run(){
        work();
        out.flush();
    }
    long mod=998244353;
    long gcd(long a,long b) {
        return a==0?b:gcd(b%a,a);
    }

    void work() {
        int n=ni();
        mod=nl();
        long[] dp1=new long[401];
        long[][] dp2=new long[n+1][n+1];
        long[][] C=new long[401][401];
        for(int j=0;j<=400;j++){
            for(int i=0;i<=j;i++){
                if(i==0||j==i){
                    C[i][j]=1;
                }else{
                    C[i][j]=(C[i-1][j-1]+C[i][j-1])%mod;
                }
            }
        }
        for(int i=1;i<=400;i++){
            for(int j=0;j<i;j++){
                dp1[i]=(dp1[i]+C[j][i-1])%mod;
            }
        }
        for(int i=1;i<=n;i++){
            dp2[i][i]=dp1[i];
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<i;j++){
                for(int k=1;k<j;k++){
                    dp2[i][j]=dp2[i][j]+((((dp2[i-k-1][j-k]*dp1[k])%mod)*C[k][j])%mod);
                    dp2[i][j]%=mod;
                }
            }
        }
        long ret=0;
        for(int j=1;j<=n;j++){
            ret=(ret+dp2[n][j])%mod;
        }
        out.println(ret);
    }

    private ArrayList<long[]>[] ngw(int n, int m) {
        ArrayList<long[]>[] graph=(ArrayList<long[]>[])new ArrayList[n];
        for(int i=0;i<n;i++) {
            graph[i]=new ArrayList<>();
        }
        for(int i=1;i<=m;i++) {
            long s=in.nextLong()-1,e=in.nextLong()-1,w=in.nextLong();
            graph[(int)s].add(new long[] {e,w});
            graph[(int)e].add(new long[] {s,w});
        }
        return graph;
    }

    private int ni() {
        return in.nextInt();
    }

    private long nl() {
        return in.nextLong();
    }

    private String ns() {
        return in.next();
    }

    private long[] na(int n) {
        long[] A=new long[n];
        for(int i=0;i<n;i++) {
            A[i]=in.nextLong();
        }
        return A;
    }
    private int[] nia(int n) {
        int[] A=new int[n];
        for(int i=0;i<n;i++) {
            A[i]=in.nextInt();
        }
        return A;
    }
}

class FastReader
{
    BufferedReader br;
    StringTokenizer st;

    public FastReader()
    {
        br=new BufferedReader(new InputStreamReader(System.in));
    }

    public String next()
    {
        while(st==null || !st.hasMoreElements())//回车，空行情况
        {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return st.nextToken();
    }

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

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


//package com.company.cf.global14;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class E {
    FastScanner in;
    PrintWriter out;
    private int M;

    public static void main(String[] args) {
        new E().solve();
    }

    private void solve() {
        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solveCase();

        out.close();
    }

    long[][] comb = new long[512][512];
    private void solveCase() {
        int n = in.nextInt();
        this.M = in.nextInt();

        calcComb(n, M);
        for (int i = 0; i < 512; i++) {
            for (int j = 0; j < 512; j++) {
                memoDivide[i][j] = -1;
                memoDP[i][j] = -1;
                dpG[i] = -1;
            }
        }

        long res = g(n);
        for (int i = 1;i <= n - 1; i++) {
            res = (res + dp(n, i)) % M;
        }

        out.println(res);
    }

    long[] dpG = new long[512];
    private long g(int n) {
        if (n < 2) return 1;
        if (n == 2) return 2;
        if (dpG[n] != -1) return dpG[n];

        long res = 0;
        for (int divide = 0; divide < n; divide++) {
            res = (res + divider(divide, n - divide - 1)) % M;
        }
        return (dpG[n] = res);
    }

    long[][] memoDivide = new long[512][512];
    private long divider(int a, int b) {
        if (a == 0 || b == 0) return 1;
        if (memoDivide[a][b] != -1) return memoDivide[a][b];
        return (memoDivide[a][b] = ((divider(a - 1, b) + divider(a, b - 1)) % M));
    }

    long[][] memoDP = new long[512][512];
    private long dp(int n, int i) {
        if (n > 0 && i == 0) return 0;
        if (n == 0 && i > 0) return 0;
        if (i > n) return 0;
        if (n == 0 && i == 0) return 1;
        if (i == n) return g(n);
        if (i <= 1) return 0;
//        if (n == 1 && i != 1) return 0;
//        if (n == 2 && i == 1) return 0;
        if (memoDP[n][i] != -1) return memoDP[n][i];

//        long res = (i * dp(n - 2, i - 1)) % M;
        long res = 0;
        for (int failure = 1; failure < n - 1 && i - failure >= 1; failure++) {
            res += ((g(failure) * comb[i][failure]) % M) * dp(n - failure - 1, i - failure);
            res %= M;
        }
        return (memoDP[n][i] = res);
    }

    private void calcComb(int n, int m) {
        for (int i = 0; i < 512; i++) {
            comb[0][i] = 0;
        }
        for (int i = 0; i < 512; i++) {
            comb[i][0] = 1;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                comb[i][j] = (comb[i - 1][j] + comb[i - 1][j - 1]) % m;
            }
        }
    }

    static class FastScanner {

        BufferedReader br;
        StringTokenizer st;

        public FastScanner(File f) {
            try {
                br = new BufferedReader(new FileReader(f));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

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

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

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

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

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

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

}


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

/**
    @author KhanhNguyenn
 */

public class C{
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.solve(in, out);
        out.close();
    }
    // main solver
    // sub-problem: 2 orders to merge together x1,x2,..,xn and y1,y2,..,ym
    // Dựa vào bài toán chia kẹp Euler, ta chứng minh dc số cách merge là
    // (m+n)C(m-1)=(m+n)C(n+1)
    static class Task{
        int M;
        public void solve(InputReader in, PrintWriter out) {
            int n= in.nextInt(); M= in.nextInt();
            if(n<=1){
                out.println(n);
                return;
            }

            // calculate nCk
            // nCk= (n-1)C(k-1)+ (n-1)Ck
            int[][] Ckn= new int[n+1][n+1];
            for(int i=0;i<=n;i++){
                Ckn[i][i]=1; Ckn[0][i]=1;
                for(int j=i-1;j>=1;j--){
                    Ckn[j][i]= add(Ckn[j-1][i-1],Ckn[j][i-1]);
                }
            }

            int ans=0;
            int[][] dp= new int[n+1][n+1];
            dp[1][1]=1;
            //dp[i][j]: number of ways to turn on first i , using j manually
            for(int i=2;i<=n;i++){
                dp[i][i]= mul(2,dp[i-1][i-1]);
                for(int j=1;j<=i-1;j++){
                    for(int k=1;k<=j;k++){
                            dp[i][j]= add(dp[i][j],mul(mul(dp[k][k],dp[i-k-1][j-k]),Ckn[k][j]));
                    }
                }
            }
            for(int i=0;i<=n;i++) ans= add(ans,dp[n][i]);
            out.println(ans);
        }

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

        public int mul(int a, int b){
            long res= (long)a*(long)b;
            res %=M;
            return (int)res;
        }

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

        // @Override
        // public int compareTo(Pair o) {
        //     if (this.x > o.x){
        //         return 1;
        //     }
        //     else if (this.x < o.x){
        //         return -1;
        //     }
        //     else{
        //         return Integer.compare(this.y, o.y);
        //     }
        // }
    }
    // fast input reader class;
    static class InputReader {
        BufferedReader br;
        StringTokenizer st;

        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
        }

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

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }
        public double nextDouble(){
            return Double.parseDouble(nextToken());
        }
        public long nextLong(){
            return Long.parseLong(nextToken());
        }
    }
}


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
 *
 * @author lucasr
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		MyScanner in = new MyScanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		EPhoenixAndComputers solver = new EPhoenixAndComputers();
		solver.solve(1, in, out);
		out.close();
	}

	static class EPhoenixAndComputers {
		public static MyScanner sc;
		public static PrintWriter out;

		public void solve(int testNumber, MyScanner sc, PrintWriter out) {
			EPhoenixAndComputers.sc = sc;
			EPhoenixAndComputers.out = out;
			int n = sc.nextInt();
			long M = sc.nextLong();
			MathLib.MOD = M;
			long[][] comb = MathLib.getComb(n + 5);
			long[] pots2 = MathLib.getPots(2, n + 2);
			long[] inv = new long[n + 5];
			for (int i = 1; i < inv.length; i++) {
				inv[i] = MathLib.inverse(i);
			}
			long[][] ret = new long[n + 1][n + 1]; // size, cant
			for (int size = 0; size <= n; size++) {
				if (size <= 1) {
					ret[size][size] = 1;
				} else if (size == 2) {
					ret[size][2] = 2;
				} else {
					long[] me = ret[size];
					me[size] = pots2[size - 1];
					for (int i = 1; i + 1 < size; i++) {
						int prev = i, next = size - i - 1;
						long tmp = pots2[i - 1];
						for (int c = 0; c <= next; c++) {
							long tot = (ret[next][c] * comb[c][c + prev]) % MathLib.MOD;
							tot = (tot * tmp) % MathLib.MOD;
							me[prev + c] += tot;
							me[prev + c] %= MathLib.MOD;
						}
					}
				}
			}
			long ans = 0;
			for (int i = 0; i <= n; i++) {
				ans += ret[n][i];
			}
			ans %= MathLib.MOD;
			out.println(ans);
		}

	}

	static class MathLib {
		public static long MOD = 1000000007;

		public static long mult(long x, long y) {
			return (x * y) % MOD;
		}

		public static long pow(long base, long exp) {
			if (exp == 0) return 1;
			if ((exp & 1) == 1) return mult(base, pow(base, exp - 1));
			return pow(mult(base, base), exp / 2);
		}

		public static long inverse(long x) {
			return pow(x, MOD - 2);
		}

		public static long[] getPots(long base, int max) {
			long[] ret = new long[max + 1];
			ret[0] = 1;
			for (int i = 1; i <= max; i++) {
				ret[i] = mult(ret[i - 1], base);
			}
			return ret;
		}

		public static long[][] getComb(int max) {
			long[][] ret = new long[max + 1][max + 1];
			for (int n = 0; n <= max; n++) {
				ret[0][n] = ret[n][n] = 1;
				for (int k = 1; k < n; k++) {
					ret[k][n] = (ret[k - 1][n - 1] + ret[k][n - 1]) % MOD;
				}
			}

			return ret;
		}

	}

	static class MyScanner {
		private BufferedReader br;
		private StringTokenizer tokenizer;

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

		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

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

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

	}
}


//make sure to make new file!
import java.io.*;
import java.util.*;

public class EG14{

   public static long MOD;
   public static int MAX = 405;

   public static long[] fac;
   public static long[] ifac;

   public static void main(String[] args)throws IOException{
      BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
      PrintWriter out = new PrintWriter(System.out);

      StringTokenizer st = new StringTokenizer(f.readLine());

      int n = Integer.parseInt(st.nextToken());
      MOD = Long.parseLong(st.nextToken());

      long[] pow2 = new long[MAX];
      pow2[0] = 1L;
      for(int k = 1; k < MAX; k++){
         pow2[k] = (2L*pow2[k-1] + MOD)%MOD;
      }

      fac = new long[MAX];
      ifac = new long[MAX];
      fac[0] = 1L;
      ifac[0] = 1L;
      for(int k = 1; k < MAX; k++){
         fac[k] = ((long)k*fac[k-1] + MOD)%MOD;
         ifac[k] = modInverse(fac[k],MOD);
      }

      long[][] dp = new long[n][n+1];                 //what n you're on, what how many computers you've turned on manually

      //initial
      for(int k = 0; k < n; k++){
         dp[k][k+1] = pow2[k];
      }

      for(int k = 2; k < n; k++){
         for(int j = 1; j <= n; j++){
            if(dp[k-2][j-1] == 0) continue;
            long start = dp[k-2][j-1];                //number for part up to previous block

            for(int add = 1; ; add++){
               if(k+add-1 >= n || j+add-1 > n) break;

               long adder = (start * pow2[add-1] + MOD)%MOD;
               adder = (adder * choose(j+add-1,j-1) + MOD)%MOD;
               dp[k+add-1][j+add-1] = (dp[k+add-1][j+add-1] + adder + MOD)%MOD;
            }
         }
      }

      long answer = 0L;
      for(int k = 1; k <= n; k++){
         answer = (answer + dp[n-1][k] + MOD)%MOD;
      }
      out.println(answer);

      out.close();
   }

   //a choose b
   public static long choose(int a, int b){
      long prod = (fac[a]*ifac[b] + MOD)%MOD;
      return (prod*ifac[a-b] + MOD)%MOD;
   }

      //from geeksforgeeks
   public static long modInverse(long a, long m)
   {
       long m0 = m;
       long y = 0L;
       long x = 1L;

       if (m == 1L)
         return 0L;

       while (a > 1L)
       {
           // q is quotient
           long q = a / m;
           long t = m;

           // m is remainder now, process same as
           // Euclid's algo
           m = a % m;
           a = t;
           t = y;

           // Update y and x
           y = x - q * y;
           x = t;
       }

       // Make x positive
       if (x < 0L)
          x += m0;

       return x;
   }

}


import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.List;
 import java.util.*;
 public class realfast implements Runnable
  {
    private static final int INF = (int) 1e9;
    long in= 1000000007;
    long fac[]= new long[1000001];
    long inv[]=new long[1000001];
    public  void solve() throws IOException
    {

        //int t = readInt();

        int n = readInt();

        long m  = readInt();

        long method[][]=new long [n+1][n+1];

        for(int i=0;i<=n;i++)
        {
            method[0][i]=1;
            method[i][0]=1;
        }

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                 for(int k=i;k>=0;k--)
                 {
                      method[i][j]= (method[i][j]%m+method[k][j-1]%m)%m;
                 }
            }
        }
         // index , total , cont
        //long dp[][][]=new  long[n+2][n+2][n+2];
        long sum[][]=new long[n+2][n+2];
        sum[0][0]=1;
      //  dp[0][0][0]=1;

        long len[][]=new long[n+1][n+1];
        for(int i=0;i<=n;i++)
        {
            len[i][0]=1;
            len[0][i]=1;
        }

        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                 len[j][i-j]= (len[j-1][i-j]%m+len[j][i-j-1]%m)%m;
            }
        }

        long gal[]=new long[2*n+1];

        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
            {
                gal[i+j]= (gal[i+j]+ len[i][j])%m;
            }
        }

        for(int i=1;i<=n;i++)
        {
            if(i==n-1)
                continue;
            for(int j=1;j<=i;j++)
            {

                   for(int k=1;k<=j;k++)
                   {

                              long val =sum[i-k][j-k];
                              val = (val*method[j-k][k])%m;

                              val =(val*gal[k-1])%m;
                              sum[i+1][j]= (sum[i+1][j]+val)%m;

                   }
            }
        }

        long ans =0;

        for(int i=1;i<=n;i++)
        {
            ans = (ans + sum[n+1][i])%m;

        }

        out.println(ans);

    }

    public int value (int seg[], int left , int right ,int index, int l, int r)
    {

            if(left>right)
            {
              return -100000000;
            }
            if(right<l||left>r)
                return -100000000;
            if(left>=l&&right<=r)
                return seg[index];
            int mid = left+(right-left)/2;
            int val = value(seg,left,mid,2*index+1,l,r);
            int val2 = value(seg,mid+1,right,2*index+2,l,r);
            return Math.max(val,val2);

    }

    public int gcd(int a , int b )
    {
      if(a<b)
      {
        int t =a;
        a=b;
        b=t;
      }
      if(a%b==0)
        return b ;
      return gcd(b,a%b);
    }
    public long pow(long n , long p,long m)
    {
         if(p==0)
            return 1;
        long val = pow(n,p/2,m);;
        val= (val*val)%m;
        if(p%2==0)
            return val;
        else
            return (val*n)%m;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static void main(String[] args) {
        new Thread(null, new realfast(), "", 128 * (1L << 20)).start();
    }

    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;
    private BufferedReader reader;
    private StringTokenizer tokenizer;
    private PrintWriter out;

    @Override
    public void run() {
        try {
            if (ONLINE_JUDGE || !new File("input.txt").exists()) {
                reader = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(System.out);
            } else {
                reader = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            }
            solve();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                // nothing
            }
            out.close();
        }
    }

    private String readString() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    @SuppressWarnings("unused")
    private int readInt() throws IOException {
        return Integer.parseInt(readString());
    }

    @SuppressWarnings("unused")
    private long readLong() throws IOException {
        return Long.parseLong(readString());
    }

    @SuppressWarnings("unused")
    private double readDouble() throws IOException {
        return Double.parseDouble(readString());
    }
}
class edge implements Comparable<edge>{
    int u ;
    int v;

    edge(int u, int v)
    {
       this.u=u;
       this.v=v;
    }
    public int compareTo(edge e)
    {
        return this.v-e.v;
    }
}


import java.io.*;
import java.text.DecimalFormat;
import java.util.*;

public class Main {

    public static final DecimalFormat DF_3 = new DecimalFormat("0.000");
    private static final long MOD = 1000000007;

    static int[] readArray(int size, InputReader in, boolean subOne) {
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = in.nextInt() + (subOne ? -1 : 0);
        }
        return a;
    }

    static long[] readLongArray(int size, InputReader in) {
        long[] a = new long[size];
        for (int i = 0; i < size; i++) {
            a[i] = in.nextLong();
        }
        return a;
    }

    static void sortArray(int[] a) {
        Random random = new Random();

        for (int i = 0; i < a.length; i++) {
            int randomPos = random.nextInt(a.length);
            int t = a[i];
            a[i] = a[randomPos];
            a[randomPos] = t;
        }
        Arrays.sort(a);
    }

    private static long[] allInvs(int n, long mod) {
        long[] inv = new long[n + 1];
        inv[1] = 1;
        for (int i = 2; i <= n; ++i) {
            inv[i] = subMod(mod, (mod / i) * inv[(int) (mod % i)] % mod, mod);
        }
        return inv;

    }

    private static long subMod(long x, long y, long mod) {
        long res = x - y;
        if (res < 0) {
            return res + mod;
        }
        return res;
    }

    private static long fastPow(long x, long y, long mod) {
        if (x == 1) {
            return 1;
        }
        if (y == 0) {
            return 1;
        }
        long p = fastPow(x, y / 2, mod) % mod;
        p = p * p % mod;
        if (y % 2 == 1) {
            p = p * x % mod;
        }
        return p;
    }

    public static void main(String[] args) throws FileNotFoundException {
//        InputReader in = new InputReader(new FileInputStream("input.txt"));
//        PrintWriter out = new PrintWriter(new BufferedOutputStream(new FileOutputStream("milkvisits.out")));
//
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

//        long start = System.currentTimeMillis();
        int n = in.nextInt();
        long mod = in.nextLong();
        long[] invs = allInvs(n + 3, mod);
        long[] facts = new long[n + 2];
        facts[0] = 1;
        long[] invFacts = new long[n + 2];
        invFacts[0] = 1;
        for (int i = 1; i < n + 2; i++) {
            facts[i] = (facts[i - 1] * i) % mod;
            invFacts[i] = (invFacts[i - 1] * invs[i]) % mod;
        }
        long[] pow2 = new long[n+3];
        pow2[0] = 1;
        for (int i = 1; i < n+3; i++) {
            pow2[i] = pow2[i-1] * 2 % mod;
        }

        long[][] dp = new long[n + 2][n + 2];
        for (int i = 2; i <= n + 1; i++) {
            dp[i][1] = invFacts[i - 1] * pow2[i - 2] % mod;
            for (int k = 2; k <= n; k++) {
                for (int j = i - 2; j >= 1; j--) {
                    dp[i][k] = (dp[i][k] + dp[j][k - 1] * pow2[ i - j - 2] % mod * invFacts[i - j - 1] % mod) % mod;
                }
            }
        }

        long ans = 0;
        for (int k = 1; k <= n; k++) {

            ans = (ans + dp[n + 1][k] * facts[n - k + 1] % mod) % mod;
        }
        out.println(ans);

        out.close();
    }

    private static void outputArray(List<Long> ans, PrintWriter out, boolean addOne) {
        StringBuilder str = new StringBuilder();
        for (int j = 0; j < ans.size(); j++) {
            long i = ans.get(j);
            long an = i + (addOne ? 1 : 0);
            str.append(an);
            if (j < ans.size() - 1) {
                str.append(' ');
            }
        }
        out.println(str);
//        out.flush();
    }

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

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public String nextString() {
            try {
                return reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

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

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

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

        public char nextChar() {
            return next().charAt(0);
        }

        public String nextWord() {
            return next();
        }

        private List<Integer>[] readTree(int n) {
            return readGraph(n, n - 1);
        }

        private List<Integer>[] readGraph(int n, int m) {
            List<Integer>[] result = new ArrayList[n];
            for (int i = 0; i < n; i++) {
                result[i] = new ArrayList<>();
            }
            for (int i = 0; i < m; i++) {
                int u = nextInt() - 1;
                int v = nextInt() - 1;
                result[u].add(v);
                result[v].add(u);
            }
            return result;
        }

    }
}


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

public class Main {
    static BufferedReader reader;
    static StringTokenizer st;
    private static void setReader() {
        reader = new BufferedReader(new InputStreamReader(System.in));
    }
    private static void updateST() throws IOException {
        if (st==null || !st.hasMoreElements()) st = new StringTokenizer(reader.readLine());
    }
    private static int nextInt() throws IOException {
        updateST();
        return Integer.parseInt(st.nextToken());
    }

    public static void main(String[] args) throws IOException {
        setReader();
        int n = nextInt(), MOD = nextInt();
        long[] pow = new long[n+2];
        pow[0] = 1;
        for (int i=1; i<=n+1; i++) pow[i] = (pow[i-1] * 2) % MOD;
        long[][] C = new long[n+2][n+2];
        for (int i=0; i<=n+1; i++) {
            C[i][0] = 1;
            for (int j=1; j<=i; j++) {
                C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
            }
        }
        long[][] dp = new long[n+2][n+1];
        dp[0][0] = 1;
        for (int i=0; i<=n; i++) {
            for (int j=0; j<=i; j++) {
                for (int k=1; i + k + 1 <= n + 1; k++) {
                    dp[i + k + 1][j + k]+=(((dp[i][j] * C[j + k][k]) % MOD * pow[k-1]) % MOD);
                    dp[i + k + 1][j + k]%=MOD;
                }
            }
        }
        long res = 0;
        for (int i=0; i<=n; i++) res = (res + dp[n+1][i]) % MOD;
        System.out.println(res);
    }
}


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

public class phoenix_and_computers {

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		String[] st = br.readLine().split(" ");
		int n = Integer.parseInt(st[0]);
		int m = Integer.parseInt(st[1]);

		long[][] ncr = ncrcoll(405, 405, m);
		int[] p2 = new int[n + 1];
		p2[0] = 1;
		for (int i = 1; i < p2.length; i++) {
			p2[i] = 2 * p2[i - 1] % m;
		}

		long[][] dp = new long[405][405];
		dp[0][0] = 1;

		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= i; j++) {
				for (int k = 1; i + k <= n; k++) {
					dp[i + k + 1][j + k] += ((dp[i][j] * p2[k - 1]) % m * ncr[j + k][k]);
					dp[i + k + 1][j + k] %= m;
				}
			}
		}

		long ans = 0;
		for (int i = 0; i <= n; i++) {
			ans = (ans + dp[n + 1][i]) % m;
		}

		System.out.println(ans);
	}

	static long[][] ncrcoll(int n, int k, int p) {
		long[][] arr = new long[n + 1][k + 1];
		for (int i = 1; i < arr.length; i++) {
			arr[i][0] = 1;
		}
		for (int i = 1; i < arr.length; i++) {
			for (int j = 1; j <= i && j < arr[0].length; j++) {
				if (i == 1 && j == 1) {
					arr[i][j] = 1;
				} else {
					arr[i][j] = (arr[i - 1][j] + arr[i - 1][j - 1]) % (p);
				}
			}
		}
		return arr;
	}

	public static long xpown(long x, long n) {
		long res = 1;
		while (n > 0) {
			if (n % 2 != 0) {
				res = (res * x) % 1000000007;
				n--;
			} else {
				x = (x * x) % 1000000007;
				n = n / 2;
			}
		}
		return res;
	}
}


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.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
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 << 29);
        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);
            EPhoenixAndComputers solver = new EPhoenixAndComputers();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class EPhoenixAndComputers {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.ri();
            int mod = in.ri();
            CachedPow2 cp = new CachedPow2(2, mod, n + 1, mod - 1);
            Combination comb = new Combination(n + 1, mod);
            long[][][] dp = new long[n + 1][n + 1][2];
            dp[0][0][0] = 1;
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= n; j++) {
                    dp[i][j][0] = dp[i - 1][j][1];
                    for (int k = 0; k < i; k++) {
                        int len = i - k;
                        int last = j - len;
                        if (last >= 0) {
                            dp[i][j][1] += dp[k][last][0] * cp.pow(len - 1) % mod * comb.combination(j, len) % mod;
                        }
                    }
                    dp[i][j][1] %= mod;
                }
            }

            long ans = 0;
            for (int i = 0; i <= n; i++) {
                ans += dp[n][i][1];
            }

            ans %= mod;
            out.println(ans);
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private static final int THRESHOLD = 32 << 10;
        private final Writer os;
        private StringBuilder cache = new StringBuilder(THRESHOLD * 2);

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

        private void afterWrite() {
            if (cache.length() < THRESHOLD) {
                return;
            }
            flush();
        }

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

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

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

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

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

        public FastOutput println() {
            return append('\n');
        }

        public FastOutput flush() {
            try {
//            boolean success = false;
//            if (stringBuilderValueField != null) {
//                try {
//                    char[] value = (char[]) stringBuilderValueField.get(cache);
//                    os.write(value, 0, cache.length());
//                    success = true;
//                } catch (Exception e) {
//                }
//            }
//            if (!success) {
                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 interface IntegerEntryIterator {
        boolean hasNext();

        void next();

        int getEntryKey();

        int getEntryValue();

    }

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

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

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

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

        public int ri() {
            return readInt();
        }

        public int readInt() {
            boolean rev = false;

            skipBlank();
            if (next == '+' || next == '-') {
                rev = next == '-';
                next = read();
            }

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

            return rev ? val : -val;
        }

    }

    static class Hasher {
        private long time = System.nanoTime() + System.currentTimeMillis() * 31L;

        public int shuffle(long z) {
            z += time;
            z = (z ^ (z >>> 33)) * 0x62a9d9ed799705f5L;
            return (int) (((z ^ (z >>> 28)) * 0xcb24d0a5c88c35b3L) >>> 32);
        }

        public int hash(int x) {
            return shuffle(x);
        }

    }

    static class CachedEulerFunction {
        private static int boundary = 1 << 16;
        private static int[] euler = MultiplicativeFunctionSieve.getInstance(boundary).getEuler();
        private static IntegerHashMap map = new IntegerHashMap(64, true);

        public static int get(int x) {
            return get(x, 2);
        }

        private static int get(int x, int begin) {
            if (x <= boundary) {
                return euler[x];
            }
            int ans = map.getOrDefault(x, -1);
            if (ans == -1) {
                int factor = findPrimeFactor(x, begin);
                int y = x;
                int exp = 1;
                while (y % factor == 0) {
                    y /= factor;
                    exp *= factor;
                }
                ans = get(y, factor + 1) * (exp - exp / factor);
                //ans = calc(x);
                map.put(x, ans);
            }
            return ans;
        }

        private static int findPrimeFactor(int x, int begin) {
            for (int i = Math.max(2, begin); i * i <= x; i++) {
                if (x % i == 0) {
                    return i;
                }
            }
            return x;
        }

    }

    static interface IntCombination {
    }

    static class MultiplicativeFunctionSieve {
        static MultiplicativeFunctionSieve instance = new MultiplicativeFunctionSieve(1 << 16);
        public int[] primes;
        public boolean[] isComp;
        public int primeLength;
        public int[] smallestPrimeFactor;
        public int[] expOfSmallestPrimeFactor;
        int limit;

        public static MultiplicativeFunctionSieve getInstance(int n) {
            if (n <= (1 << 16)) {
                return instance;
            }
            return new MultiplicativeFunctionSieve(n);
        }

        public int[] getEuler() {
            int[] euler = new int[limit + 1];
            euler[1] = 1;
            for (int i = 2; i <= limit; i++) {
                if (!isComp[i]) {
                    euler[i] = i - 1;
                } else {
                    if (expOfSmallestPrimeFactor[i] == i) {
                        euler[i] = i - i / smallestPrimeFactor[i];
                    } else {
                        euler[i] = euler[expOfSmallestPrimeFactor[i]] * euler[i / expOfSmallestPrimeFactor[i]];
                    }
                }
            }
            return euler;
        }

        public MultiplicativeFunctionSieve(int limit) {
            this.limit = limit;
            isComp = new boolean[limit + 1];
            primes = new int[limit + 1];
            expOfSmallestPrimeFactor = new int[limit + 1];
            smallestPrimeFactor = new int[limit + 1];
            primeLength = 0;
            for (int i = 2; i <= limit; i++) {
                if (!isComp[i]) {
                    primes[primeLength++] = i;
                    expOfSmallestPrimeFactor[i] = smallestPrimeFactor[i] = i;
                }
                for (int j = 0, until = limit / i; j < primeLength && primes[j] <= until; j++) {
                    int pi = primes[j] * i;
                    smallestPrimeFactor[pi] = primes[j];
                    expOfSmallestPrimeFactor[pi] = smallestPrimeFactor[i] == primes[j]
                            ? (expOfSmallestPrimeFactor[i] * expOfSmallestPrimeFactor[primes[j]])
                            : expOfSmallestPrimeFactor[primes[j]];
                    isComp[pi] = true;
                    if (i % primes[j] == 0) {
                        break;
                    }
                }
            }
        }

    }

    static class Factorial {
        int[] fact;
        int[] inv;
        int mod;

        public int getMod() {
            return mod;
        }

        public Factorial(int[] fact, int[] inv, int mod) {
            this.mod = mod;
            this.fact = fact;
            this.inv = inv;
            fact[0] = inv[0] = 1;
            int n = Math.min(fact.length, mod);
            for (int i = 1; i < n; i++) {
                fact[i] = i;
                fact[i] = (int) ((long) fact[i] * fact[i - 1] % mod);
            }
            if (n - 1 >= 0) {
                inv[n - 1] = BigInteger.valueOf(fact[n - 1]).modInverse(BigInteger.valueOf(mod)).intValue();
            }
            for (int i = n - 2; i >= 1; i--) {
                inv[i] = (int) ((long) inv[i + 1] * (i + 1) % mod);
            }
        }

        public Factorial(int limit, int mod) {
            this(new int[Math.min(limit + 1, mod)], new int[Math.min(limit + 1, mod)], mod);
        }

        public int fact(int n) {
            if (n >= mod) {
                return 0;
            }
            return fact[n];
        }

        public int invFact(int n) {
            if (n >= mod) {
                throw new IllegalArgumentException();
            }
            return inv[n];
        }

    }

    static class CachedPow2 {
        private int[] first;
        private int[] second;
        private int mod;
        private int low;
        private int mask;
        private int phi;
        private int xphi;

        public CachedPow2(int x, int mod) {
            this(x, mod, CachedEulerFunction.get(mod));
        }

        public CachedPow2(int x, int mod, int phi) {
            this(x, mod, mod, phi);
        }

        public CachedPow2(int x, int mod, int limit, int phi) {
            this.phi = phi;
            limit = Math.min(limit, mod);
            this.mod = mod;
            int log = Log2.ceilLog(limit + 1);
            low = (log + 1) / 2;
            mask = (1 << low) - 1;
            first = new int[1 << low];
            second = new int[1 << log - low];
            first[0] = 1;
            for (int i = 1; i < first.length; i++) {
                first[i] = (int) ((long) x * first[i - 1] % mod);
            }
            second[0] = 1;
            long step = (long) x * first[first.length - 1] % mod;
            for (int i = 1; i < second.length; i++) {
                second[i] = (int) (second[i - 1] * step % mod);
            }

            xphi = DigitUtils.modPow(x, phi, mod);
        }

        public int pow(int exp) {
            return (int) ((long) first[exp & mask] * second[exp >> low] % mod);
        }

    }

    static class DigitUtils {
        private DigitUtils() {
        }

        public static int mod(long x, int mod) {
            if (x < -mod || x >= mod) {
                x %= mod;
            }
            if (x < 0) {
                x += mod;
            }
            return (int) x;
        }

        public static int mod(int x, int mod) {
            if (x < -mod || x >= mod) {
                x %= mod;
            }
            if (x < 0) {
                x += mod;
            }
            return x;
        }

        public static int modPow(int x, long n, int m) {
            if (n == 0) {
                return DigitUtils.mod(1, m);
            }
            int ans = modPow(x, n / 2, m);
            ans = DigitUtils.mod((long) ans * ans, m);
            if (n % 2 == 1) {
                ans = DigitUtils.mod((long) ans * x, m);
            }
            return ans;
        }

    }

    static class Combination implements IntCombination {
        final Factorial factorial;
        int modVal;

        public Combination(Factorial factorial) {
            this.factorial = factorial;
            this.modVal = factorial.getMod();
        }

        public Combination(int limit, int mod) {
            this(new Factorial(limit, mod));
        }

        public int combination(int m, int n) {
            if (n > m || n < 0) {
                return 0;
            }
            return (int) ((long) factorial.fact(m) * factorial.invFact(n) % modVal * factorial.invFact(m - n) % modVal);
        }

    }

    static class Log2 {
        public static int ceilLog(int x) {
            if (x <= 0) {
                return 0;
            }
            return 32 - Integer.numberOfLeadingZeros(x - 1);
        }

    }

    static class IntegerHashMap {
        private int now;
        private int[] slot;
        private int[] version;
        private int[] next;
        private int[] keys;
        private int[] values;
        private int alloc;
        private boolean[] removed;
        private int mask;
        private int size;
        private boolean rehash;
        private Hasher hasher = new Hasher();

        public IntegerHashMap(int cap, boolean rehash) {
            now = 1;
            this.mask = (1 << (32 - Integer.numberOfLeadingZeros(cap - 1))) - 1;
            slot = new int[mask + 1];
            version = new int[slot.length];
            next = new int[cap + 1];
            keys = new int[cap + 1];
            values = new int[cap + 1];
            removed = new boolean[cap + 1];
            this.rehash = rehash;
        }

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

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

        private void rehash() {
            int[] newSlots = new int[Math.max(16, slot.length * 2)];
            int[] newVersions = new int[newSlots.length];
            int newMask = newSlots.length - 1;
            for (int i = 0; i < slot.length; i++) {
                access(i);
                if (slot[i] == 0) {
                    continue;
                }
                int head = slot[i];
                while (head != 0) {
                    int n = next[head];
                    int s = hash(keys[head]) & newMask;
                    next[head] = newSlots[s];
                    newSlots[s] = head;
                    head = n;
                }
            }
            this.slot = newSlots;
            this.version = newVersions;
            now = 0;
            this.mask = newMask;
        }

        private int hash(int x) {
            return hasher.hash(x);
        }

        public void put(int x, int y) {
            put(x, y, true);
        }

        public void put(int x, int y, boolean cover) {
            int h = hash(x);
            int s = h & mask;
            access(s);
            if (slot[s] == 0) {
                alloc();
                slot[s] = alloc;
                keys[alloc] = x;
                values[alloc] = y;
            } else {
                int index = findIndexOrLastEntry(s, x);
                if (keys[index] != x) {
                    alloc();
                    next[index] = alloc;
                    keys[alloc] = x;
                    values[alloc] = y;
                } else if (cover) {
                    values[index] = y;
                }
            }
            if (rehash && size >= slot.length) {
                rehash();
            }
        }

        public int getOrDefault(int x, int def) {
            int h = hash(x);
            int s = h & mask;
            access(s);
            if (slot[s] == 0) {
                return def;
            }
            int index = findIndexOrLastEntry(s, x);
            return keys[index] == x ? values[index] : def;
        }

        private int findIndexOrLastEntry(int s, int x) {
            int iter = slot[s];
            while (keys[iter] != x) {
                if (next[iter] != 0) {
                    iter = next[iter];
                } else {
                    return iter;
                }
            }
            return iter;
        }

        private void access(int i) {
            if (version[i] != now) {
                version[i] = now;
                slot[i] = 0;
            }
        }

        public IntegerEntryIterator iterator() {
            return new IntegerEntryIterator() {
                int index = 1;
                int readIndex = -1;

                public boolean hasNext() {
                    while (index <= alloc && removed[index]) {
                        index++;
                    }
                    return index <= alloc;
                }

                public int getEntryKey() {
                    return keys[readIndex];
                }

                public int getEntryValue() {
                    return values[readIndex];
                }

                public void next() {
                    if (!hasNext()) {
                        throw new IllegalStateException();
                    }
                    readIndex = index;
                    index++;
                }
            };
        }

        public String toString() {
            IntegerEntryIterator iterator = iterator();
            StringBuilder builder = new StringBuilder("{");
            while (iterator.hasNext()) {
                iterator.next();
                builder.append(iterator.getEntryKey()).append("->").append(iterator.getEntryValue()).append(',');
            }
            if (builder.charAt(builder.length() - 1) == ',') {
                builder.setLength(builder.length() - 1);
            }
            builder.append('}');
            return builder.toString();
        }

    }
}