//Utilities
import java.io.*;
import java.util.*;

public class a {
	static int t;
	static int n, k;
	static ComboMod c;
	static long[][] dp;
	static final int MOD = 998244353;

	public static void main(String[] args) throws IOException {
		t = 1;
		while (t-- > 0) {
			n = in.iscan(); k = in.iscan();
			c = new ComboMod(n, MOD);
			dp = new long[n][k+1];
			for (int i = 0; i < n; i++) {
				for (int j = 0; j <= k; j++) {
					dp[i][j] = -1;
				}
			}
			out.println(attack(0, 1));
		}
		out.close();
	}

	static long attack(int i, int j) {
		if (dp[i][j] != -1) {
			return dp[i][j];
		}
		if (j == k) {
			return dp[i][j] = 1;
		}
		long ret = 0;
		for (int cnt = 0; i + cnt < n; cnt++) {
			long e = cnt * i + (cnt - 1) * cnt / 2;
			long add = c.ncr(n - 1 - i, cnt) * UTILITIES.fast_pow_mod(k-j+1, e, MOD) % MOD * attack(i + cnt, j+1) % MOD;
			ret = (ret + add) % MOD;
		}
		return dp[i][j] = ret;
	}

	static class ComboMod {
		int n, MOD;
		long[] fac, facinv, inv;

		ComboMod(int n, int MOD) {
			this.n = n; this.MOD = MOD;
			fac = new long[n+1]; facinv = new long[n+1]; inv = new long[n+1];
		    fac[0] = facinv[0] = 1; inv[1] = 1;
		    for (int i = 2; i <= n; i++) {
		    	inv[i] =  (inv[MOD % i] * (-MOD / i) % MOD + MOD) % MOD;
		    }
		    for(int i = 1; i <= n; i++){
		      fac[i] = fac[i-1] * i % MOD;
		      facinv[i] = facinv[i-1] * inv[i] % MOD;
		    }
		}
		long fac(int n) { return fac[n]; }
		long facinv(int n) { return facinv[n]; }
		long inv(int n) { return inv[n]; }
		long ncr(int n, int k) { return n < k || k < 0 ? 0 : fac[n] * facinv[k] % MOD * facinv[n-k] % MOD; }
	}

	static INPUT in = new INPUT(System.in);
	static PrintWriter out = new PrintWriter(System.out);
	private static class INPUT {

		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar, numChars;

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

		public INPUT (String file) throws IOException {
			this.stream = new FileInputStream (file);
		}

		public int cscan () throws IOException {
			if (curChar >= numChars) {
				curChar = 0;
				numChars = stream.read (buf);
			}

			if (numChars == -1)
				return numChars;

			return buf[curChar++];
		}

		public int iscan () throws IOException {
			int c = cscan (), sgn = 1;

			while (space (c))
				c = cscan ();

			if (c == '-') {
				sgn = -1;
				c = cscan ();
			}

			int res = 0;

			do {
				res = (res << 1) + (res << 3);
				res += c - '0';
				c = cscan ();
			}
			while (!space (c));

			return res * sgn;
		}

		public String sscan () throws IOException {
			int c = cscan ();

			while (space (c))
				c = cscan ();

			StringBuilder res = new StringBuilder ();

			do {
				res.appendCodePoint (c);
				c = cscan ();
			}
			while (!space (c));

			return res.toString ();
		}

		public double dscan () throws IOException {
			int c = cscan (), sgn = 1;

			while (space (c))
				c = cscan ();

			if (c == '-') {
				sgn = -1;
				c = cscan ();
			}

			double res = 0;

			while (!space (c) && c != '.') {
				if (c == 'e' || c == 'E')
					return res * UTILITIES.fast_pow (10, iscan ());

				res *= 10;
				res += c - '0';
				c = cscan ();
			}

			if (c == '.') {
				c = cscan ();
				double m = 1;

				while (!space (c)) {
					if (c == 'e' || c == 'E')
						return res * UTILITIES.fast_pow (10, iscan ());

					m /= 10;
					res += (c - '0') * m;
					c = cscan ();
				}
			}

			return res * sgn;
		}

		public long lscan () throws IOException {
			int c = cscan (), sgn = 1;

			while (space (c))
				c = cscan ();

			if (c == '-') {
				sgn = -1;
				c = cscan ();
			}

			long res = 0;

			do {
				res = (res << 1) + (res << 3);
				res += c - '0';
				c = cscan ();
			}
			while (!space (c));

			return res * sgn;
		}

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

	public static class UTILITIES {

		static final double EPS = 10e-6;

		public static void sort(int[] a, boolean increasing) {
			ArrayList<Integer> arr = new ArrayList<Integer>();
			int n = a.length;
			for (int i = 0; i < n; i++) {
				arr.add(a[i]);
			}
			Collections.sort(arr);
			for (int i = 0; i < n; i++) {
				if (increasing) {
					a[i] = arr.get(i);
				}
				else {
					a[i] = arr.get(n-1-i);
				}
			}
		}

		public static void sort(long[] a, boolean increasing) {
			ArrayList<Long> arr = new ArrayList<Long>();
			int n = a.length;
			for (int i = 0; i < n; i++) {
				arr.add(a[i]);
			}
			Collections.sort(arr);
			for (int i = 0; i < n; i++) {
				if (increasing) {
					a[i] = arr.get(i);
				}
				else {
					a[i] = arr.get(n-1-i);
				}
			}
		}

		public static void sort(double[] a, boolean increasing) {
			ArrayList<Double> arr = new ArrayList<Double>();
			int n = a.length;
			for (int i = 0; i < n; i++) {
				arr.add(a[i]);
			}
			Collections.sort(arr);
			for (int i = 0; i < n; i++) {
				if (increasing) {
					a[i] = arr.get(i);
				}
				else {
					a[i] = arr.get(n-1-i);
				}
			}
		}

		public static int lower_bound (int[] arr, int x) {
			int low = 0, high = arr.length, mid = -1;

			while (low < high) {
				mid = (low + high) / 2;

				if (arr[mid] >= x)
					high = mid;
				else
					low = mid + 1;
			}

			return low;
		}

		public static int upper_bound (int[] arr, int x) {
			int low = 0, high = arr.length, mid = -1;

			while (low < high) {
				mid = (low + high) / 2;

				if (arr[mid] > x)
					high = mid;
				else
					low = mid + 1;
			}

			return low;
		}

		public static void updateMap(HashMap<Integer, Integer> map, int key, int v) {
			if (!map.containsKey(key)) {
				map.put(key, v);
			}
			else {
				map.put(key, map.get(key) + v);
			}
			if (map.get(key) == 0) {
				map.remove(key);
			}
		}

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

		public static long lcm (long a, long b) {
			return a * b / gcd (a, b);
		}

		public static long fast_pow_mod (long b, long x, int mod) {
			if (x == 0) return 1;
			if (x == 1) return b;
			if (x % 2 == 0) return fast_pow_mod (b * b % mod, x / 2, mod) % mod;

			return b * fast_pow_mod (b * b % mod, x / 2, mod) % mod;
		}

		public static long fast_pow (long b, long x) {
			if (x == 0) return 1;
			if (x == 1) return b;
			if (x % 2 == 0) return fast_pow (b * b, x / 2);

			return b * fast_pow (b * b, x / 2);
		}

		public static long choose (long n, long k) {
			k = Math.min (k, n - k);
			long val = 1;

			for (int i = 0; i < k; ++i)
				val = val * (n - i) / (i + 1);

			return val;
		}

		public static long permute (int n, int k) {
			if (n < k) return 0;
			long val = 1;

			for (int i = 0; i < k; ++i)
				val = (val * (n - i));

			return val;
		}

		// start of permutation and lower/upper bound template
		public static void nextPermutation(int[] nums) {
		    //find first decreasing digit
		    int mark = -1;
		    for (int i = nums.length - 1; i > 0; i--) {
		        if (nums[i] > nums[i - 1]) {
		            mark = i - 1;
		            break;
		        }
		    }

		    if (mark == -1) {
		        reverse(nums, 0, nums.length - 1);
		        return;
		    }

		    int idx = nums.length-1;
		    for (int i = nums.length-1; i >= mark+1; i--) {
		        if (nums[i] > nums[mark]) {
		            idx = i;
		            break;
		        }
		    }

		    swap(nums, mark, idx);

		    reverse(nums, mark + 1, nums.length - 1);
		}

		public static void swap(int[] nums, int i, int j) {
		    int t = nums[i];
		    nums[i] = nums[j];
		    nums[j] = t;
		}

		public static void reverse(int[] nums, int i, int j) {
		    while (i < j) {
		        swap(nums, i, j);
		        i++;
		        j--;
		    }
		}

		static int lower_bound (int[] arr, int hi, int cmp) {
			int low = 0, high = hi, mid = -1;
			while (low < high) {
				mid = (low + high) / 2;
				if (arr[mid] >= cmp) high = mid;
				else low = mid + 1;
			}
			return low;
		}

		static int upper_bound (int[] arr, int hi, int cmp) {
			int low = 0, high = hi, mid = -1;
			while (low < high) {
				mid = (low + high) / 2;
				if (arr[mid] > cmp) high = mid;
				else low = mid + 1;
			}
			return low;
		}
		// end of permutation and lower/upper bound template
	}
}


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

public final class Main {

    //int 2e9 - long 9e18
    static PrintWriter out = new PrintWriter(System.out);
    static FastReader in = new FastReader();
    static Pair[] moves = new Pair[]{new Pair(-1, 0), new Pair(0, 1), new Pair(1, 0), new Pair(0, -1)};
    static int mod = (int) (1e9 + 7);
    static int mod2 = 998244353;

    public static void main(String[] args) {
        initializeFactorial(250, mod2);
        int tt = 1;
        while (tt-- > 0) {
            solve();
        }
        out.flush();
    }

    public static void solve() {
        int n = i();
        int k = i();

        int[] e = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            e[i] = i * (i - 1) / 2;
        }
        int[][] dp = new int[n + 1][k + 1];
        dp[1][0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < k; j++) {
                // color j+1
                for (int l = 0; l <= n - i; l++) {
                    int rem = n - i;
                    int cof = binomialCoefficient(rem, l, mod2);
                    long add = (long) dp[i][j] * cof;
                    add %= mod2;
                    add *= pow(k - j,e[i + l] - e[i] - l , mod2);
                    add %= mod2;
                    dp[i + l][j + 1] += add;
                    dp[i + l][j + 1] %= mod2;
                }
            }
        }

        out.println(dp[n][k]);
    }

    static long[] fac;
    static long[] inv;

    static void initializeFactorial(int n, int mod) {
        fac = new long[n + 1];
        inv = new long[n + 1];
        long[] v = new long[fac.length];
        fac[0] = inv[0] = 1;
        for (int i = 1; i < fac.length; i++) {
            v[i] = i == 1 ? 1 : v[i - mod % i] * (mod / i + 1);
            v[i] %= mod;
            fac[i] = fac[i - 1] * i;
            fac[i] %= mod;
            inv[i] = inv[i - 1] * v[i];
            inv[i] %= mod;
        }
    }

    static int binomialCoefficient(int n, int k, int m) {
        long res = fac[n] * inv[k];
        res %= m;
        res *= inv[n - k];
        return (int) (res % m);
    }

    // (10,5) = 2 ,(11,5) = 3
    static long upperDiv(long a, long b) {
        return (a / b) + ((a % b == 0) ? 0 : 1);
    }

    static long sum(int[] a) {
        long sum = 0;
        for (int x : a) {
            sum += x;
        }
        return sum;
    }

    static int[] preint(int[] a) {
        int[] pre = new int[a.length + 1];
        pre[0] = 0;
        for (int i = 0; i < a.length; i++) {
            pre[i + 1] = pre[i] + a[i];
        }
        return pre;
    }

    static long[] pre(int[] a) {
        long[] pre = new long[a.length + 1];
        pre[0] = 0;
        for (int i = 0; i < a.length; i++) {
            pre[i + 1] = pre[i] + a[i];
        }
        return pre;
    }

    static long[] post(int[] a) {
        long[] post = new long[a.length + 1];
        post[0] = 0;
        for (int i = 0; i < a.length; i++) {
            post[i + 1] = post[i] + a[a.length - 1 - i];
        }
        return post;
    }

    static long[] pre(long[] a) {
        long[] pre = new long[a.length + 1];
        pre[0] = 0;
        for (int i = 0; i < a.length; i++) {
            pre[i + 1] = pre[i] + a[i];
        }
        return pre;
    }

    static void print(char A[]) {
        for (char c : A) {
            out.print(c);
        }
        out.println();
    }

    static void print(boolean A[]) {
        for (boolean c : A) {
            out.print(c + " ");
        }
        out.println();
    }

    static void print(int A[]) {
        for (int c : A) {
            out.print(c + " ");
        }
        out.println();
    }

    static void print(long A[]) {
        for (long i : A) {
            out.print(i + " ");
        }
        out.println();
    }

    static void print(List<Integer> A) {
        for (int a : A) {
            out.print(a + " ");
        }
    }

    static int i() {
        return in.nextInt();
    }

    static long l() {
        return in.nextLong();
    }

    static double d() {
        return in.nextDouble();
    }

    static String s() {
        return in.nextLine();
    }

    static String c() {
        return in.next();
    }

    static int[][] inputWithIdx(int N) {
        int A[][] = new int[N][2];
        for (int i = 0; i < N; i++) {
            A[i] = new int[]{i, in.nextInt()};
        }
        return A;
    }

    static int[] input(int N) {
        int A[] = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = in.nextInt();
        }
        return A;
    }

    static long[] inputLong(int N) {
        long A[] = new long[N];
        for (int i = 0; i < A.length; i++) {
            A[i] = in.nextLong();
        }
        return A;
    }

    static int GCD(int a, int b) {
        if (b == 0) {
            return a;
        } else {
            return GCD(b, a % b);
        }
    }

    static long GCD(long a, long b) {
        if (b == 0) {
            return a;
        } else {
            return GCD(b, a % b);
        }
    }

    static long LCM(int a, int b) {
        return (long) a / GCD(a, b) * b;
    }

    static long LCM(long a, long b) {
        return a / GCD(a, b) * b;
    }

    // find highest i which satisfy a[i]<=x
    static int lowerbound(int[] a, int x) {
        int l = 0;
        int r = a.length - 1;
        while (l < r) {
            int m = (l + r + 1) / 2;
            if (a[m] <= x) {
                l = m;
            } else {
                r = m - 1;
            }
        }
        return l;
    }

    static void shuffle(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int rand = (int) (Math.random() * arr.length);
            int temp = arr[rand];
            arr[rand] = arr[i];
            arr[i] = temp;
        }
    }

    static void shuffleAndSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int rand = (int) (Math.random() * arr.length);
            int temp = arr[rand];
            arr[rand] = arr[i];
            arr[i] = temp;
        }
        Arrays.sort(arr);
    }

    static void shuffleAndSort(int[][] arr, Comparator<? super int[]> comparator) {
        for (int i = 0; i < arr.length; i++) {
            int rand = (int) (Math.random() * arr.length);
            int[] temp = arr[rand];
            arr[rand] = arr[i];
            arr[i] = temp;
        }
        Arrays.sort(arr, comparator);
    }

    static void shuffleAndSort(long[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int rand = (int) (Math.random() * arr.length);
            long temp = arr[rand];
            arr[rand] = arr[i];
            arr[i] = temp;
        }
        Arrays.sort(arr);
    }

    static boolean isPerfectSquare(double number) {
        double sqrt = Math.sqrt(number);
        return ((sqrt - Math.floor(sqrt)) == 0);
    }

    static void swap(int A[], int a, int b) {
        int t = A[a];
        A[a] = A[b];
        A[b] = t;
    }

    static void swap(char A[], int a, int b) {
        char t = A[a];
        A[a] = A[b];
        A[b] = t;
    }

    static long pow(long a, long b, int mod) {
        long pow = 1;
        long x = a;
        while (b != 0) {
            if ((b & 1) != 0) {
                pow = (pow * x) % mod;
            }
            x = (x * x) % mod;
            b /= 2;
        }
        return pow;
    }

    static long pow(long a, long b) {
        long pow = 1;
        long x = a;
        while (b != 0) {
            if ((b & 1) != 0) {
                pow *= x;
            }
            x = x * x;
            b /= 2;
        }
        return pow;
    }

    static long modInverse(long x, int mod) {
        return pow(x, mod - 2, mod);
    }

    static boolean isPrime(long N) {
        if (N <= 1) {
            return false;
        }
        if (N <= 3) {
            return true;
        }
        if (N % 2 == 0 || N % 3 == 0) {
            return false;
        }
        for (int i = 5; i * i <= N; i = i + 6) {
            if (N % i == 0 || N % (i + 2) == 0) {
                return false;
            }
        }
        return true;
    }

    public static String reverse(String str) {
        if (str == null) {
            return null;
        }
        return new StringBuilder(str).reverse().toString();
    }

    public static void reverse(int[] arr) {
        for (int i = 0; i < arr.length / 2; i++) {
            int tmp = arr[i];
            arr[arr.length - 1 - i] = tmp;
            arr[i] = arr[arr.length - 1 - i];
        }
    }

    public static String repeat(char ch, int repeat) {
        if (repeat <= 0) {
            return "";
        }
        final char[] buf = new char[repeat];
        for (int i = repeat - 1; i >= 0; i--) {
            buf[i] = ch;
        }
        return new String(buf);
    }

    public static int[] manacher(String s) {
        char[] chars = s.toCharArray();
        int n = s.length();
        int[] d1 = new int[n];
        for (int i = 0, l = 0, r = -1; i < n; i++) {
            int k = (i > r) ? 1 : Math.min(d1[l + r - i], r - i + 1);
            while (0 <= i - k && i + k < n && chars[i - k] == chars[i + k]) {
                k++;
            }
            d1[i] = k--;
            if (i + k > r) {
                l = i - k;
                r = i + k;
            }
        }
        return d1;
    }

    public static int[] kmp(String s) {
        int n = s.length();
        int[] res = new int[n];
        for (int i = 1; i < n; ++i) {
            int j = res[i - 1];
            while (j > 0 && s.charAt(i) != s.charAt(j)) {
                j = res[j - 1];
            }
            if (s.charAt(i) == s.charAt(j)) {
                ++j;
            }
            res[i] = j;
        }
        return res;
    }
}

class Pair {

    int i;
    int j;

    Pair(int i, int j) {
        this.i = i;
        this.j = j;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Pair pair = (Pair) o;
        return i == pair.i && j == pair.j;
    }

    @Override
    public int hashCode() {
        return Objects.hash(i, j);
    }
}

class ThreePair {

    int i;
    int j;
    int k;

    ThreePair(int i, int j, int k) {
        this.i = i;
        this.j = j;
        this.k = k;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        ThreePair pair = (ThreePair) o;
        return i == pair.i && j == pair.j && k == pair.k;
    }

    @Override
    public int hashCode() {
        return Objects.hash(i, j);
    }
}

class FastReader {

    BufferedReader br;
    StringTokenizer st;

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

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

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

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

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

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

class Node {

    int val;

    public Node(int val) {
        this.val = val;
    }
}

class ST {

    int n;
    Node[] st;

    ST(int n) {
        this.n = n;
        st = new Node[4 * Integer.highestOneBit(n)];
    }

    void build(Node[] nodes) {
        build(0, 0, n - 1, nodes);
    }

    private void build(int id, int l, int r, Node[] nodes) {
        if (l == r) {
            st[id] = nodes[l];
            return;
        }
        int mid = (l + r) >> 1;
        build((id << 1) + 1, l, mid, nodes);
        build((id << 1) + 2, mid + 1, r, nodes);
        st[id] = comb(st[(id << 1) + 1], st[(id << 1) + 2]);
    }

    void update(int i, Node node) {
        update(0, 0, n - 1, i, node);
    }

    private void update(int id, int l, int r, int i, Node node) {
        if (i < l || r < i) {
            return;
        }
        if (l == r) {
            st[id] = node;
            return;
        }
        int mid = (l + r) >> 1;
        update((id << 1) + 1, l, mid, i, node);
        update((id << 1) + 2, mid + 1, r, i, node);
        st[id] = comb(st[(id << 1) + 1], st[(id << 1) + 2]);
    }

    Node get(int x, int y) {
        return get(0, 0, n - 1, x, y);
    }

    private Node get(int id, int l, int r, int x, int y) {
        if (x > r || y < l) {
            return new Node(0);
        }
        if (x <= l && r <= y) {
            return st[id];
        }
        int mid = (l + r) >> 1;
        return comb(get((id << 1) + 1, l, mid, x, y), get((id << 1) + 2, mid + 1, r, x, y));
    }

    Node comb(Node a, Node b) {
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        return new Node(GCD(a.val, b.val));
    }

    static int GCD(int a, int b) {
        if (b == 0) {
            return a;
        } else {
            return GCD(b, a % b);
        }
    }
}


import java.util.*;
import java.util.Map.Entry;

import java.math.*;
import java.io.*;

public class Main {
	public static void main(String[] args) throws FileNotFoundException {
		InputReader in = new InputReader(System.in);
		// Scanner in = new Scanner(System.in);
		// Scanner in = new Scanner(new BufferedReader(new
		// InputStreamReader(System.in)));
		PrintWriter out = new PrintWriter(System.out);
		// InputReader in = new InputReader(new
		// File("ethan_traverses_a_tree.txt"));
		// PrintWriter out = new PrintWriter(new
		// File("ethan_traverses_a_tree-output.txt"))

		final long mod = 998244353;

		int n = in.nextInt();
		int k = in.nextInt();

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

		for (int i = 0; i <= n; i++) {
			c[i][0] = c[i][i] = 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 + 1][k + 1];
		long[][] sum = new long[n + 1][k + 1];

		dp[1][0] = 1;
		for (int j = 0; j <= k; j++) {
			sum[1][j] = 1;
		}

		for (int i = 2; i <= n; i++) {
			for (int j = 1; j <= k; j++) {
				long sumnow = 0;
				for (int u = 1; u < i; u++) {
					long now = (sum[i - u][j - 1] * c[i - 1][u]) % mod;
					int edgecount = ((i - u - 1) + (i - 2)) * u / 2;
					long p = powmod(k - j + 1, edgecount, mod);

					sumnow = (sumnow + (now * p) % mod) % mod;
				}
				dp[i][j] = sumnow;
			}

			for (int j = 1; j <= k; j++) {
				sum[i][j] = (sum[i][j - 1] + dp[i][j]) % mod;
			}
		}

		out.printf("%d\n", sum[n][k]);

		out.close();
	}

	static public long inverse(long a, int p) {
		return powmod(a, p - 2, p);
	}

	static public long powmod(long a, long n, long mod) {
		long result = 1;
		long p = a;

		while (n != 0) {
			if (n % 2 == 1) {
				result = (result * p) % mod;
			}
			p = (p * p) % mod;
			n = n / 2;
		}

		return result;
	}

	static class InputReader {
		BufferedReader br;
		StringTokenizer st;

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

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

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

		public boolean hasNext() {
			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;
		}

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

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

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


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

public class _1657_E {
    static final long MOD = 998244353;
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);
        StringTokenizer line = new StringTokenizer(in.readLine());
        int n = Integer.parseInt(line.nextToken());
        int k = Integer.parseInt(line.nextToken());
        long[][][] dp = new long[n][k + 1][n];
        long[][] psum = new long[n][k + 1];
        for(int i = 1; i <= k; i++) {
            dp[1][i][1] = 1;
            psum[1][i] = modadd(psum[1][i - 1], 1);
        }
        long res = 0;
        for(int i = 2; i < n; i++) {
            for(int j = 1; j <= k; j++) {
                psum[i][j] = psum[i][j - 1];
                for(int a = 1; a <= i; a++) {
                    if(a > 1) {
                        long mult = modmult(modmult(i, modinv(a)), binpow(k - j + 1, i - 1));
                        dp[i][j][a] = modmult(dp[i - 1][j][a - 1], mult);
                    }else {
                        long mult = modmult(i, binpow(k - j + 1, i - 1));
                        dp[i][j][a] = modmult(psum[i - 1][j - 1], mult);
                    }
                    psum[i][j] = modadd(psum[i][j], dp[i][j][a]);
                    if(i == n - 1) {
                        res = modadd(res, dp[i][j][a]);
                    }
                }
            }
        }
        out.println(res);
        in.close();
        out.close();
    }
    static long modadd(long a, long b) {
        return (a + b + MOD) % MOD;
    }
    static long modmult(long a, long b) {
        return a * b % MOD;
    }
    static long modinv(long a) {
        return binpow(a, MOD - 2);
    }
    static long binpow(long a, long b) {
        if(b == 0) {
            return 1;
        }
        long small = binpow(a, b / 2);
        if(b % 2 == 0) {
            return modmult(small, small);
        }else {
            return modmult(modmult(small, small), a);
        }
    }
}


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

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

    int N = (int) 2e5 + 10;
    int MOD = (int) 1e9 + 7;

    int n;
    long[] t1 = new long[N];
    long[] t2 = new long[N];

    void solve() {
        n = in.nextInt(); int Q = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = in.nextInt();
        int[] w = new int[n];
        for (int i = 0; i < n; i++) w[i] = in.nextInt();

        for (int i = 0; i < n; i++) a[i] = (a[i] - i + MOD) % MOD;

        for (int i = 0; i < n; i++) {
            add(t1, i, w[i]);
            add(t2, i, (long) a[i] * w[i] % MOD);
        }

        while (Q-- > 0) {
            int x = in.nextInt();
            if (x < 0) {
                int i = -x - 1, nw = in.nextInt();
                long delta1 = nw - w[i];
                long delta2 = (a[i] * nw % MOD - a[i] * w[i] % MOD + MOD) % MOD;
                w[i] = nw;
                add(t1, i, delta1);
                add(t2, i, delta2);
            } else {
                int l = x - 1, r = in.nextInt();
                long tot = sum(t1, l, r);
                int lb = l, ub = r;
                while (ub - lb > 1) {
                    int m = (lb + ub) >> 1;
                    if (sum(t1, l, m) * 2 <= tot) lb = m;
                    else ub = m;
                }
                int k = lb;
                long ans = (a[k] * (sum(t1, l, k) % MOD) % MOD - sum(t2, l, k) % MOD + MOD) % MOD;
                ans = (ans + (sum(t2, k + 1, r) % MOD - a[k] * (sum(t1, k + 1, r) % MOD) % MOD + MOD) % MOD) % MOD;
                out.println(ans);
            }
        }
    }

    long sum(long[] t, int l, int r) {
        return sum(t, r - 1) - sum(t, l - 1);
    }

    long sum(long[] t, int i) {
        long res = 0;
        for (int x = i; x >= 0; x = (x & x + 1) - 1) res += t[x];
        return res;
    }

    void add(long[] t, int i, long delta) {
        for (int x = i; x < n; x = x | x + 1) t[x] += delta;
    }

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

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

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

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

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

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

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


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

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

    int N = (int) 2e5 + 10;
    int MOD = (int) 1e9 + 7;

    int n;
    long[] t1 = new long[N];
    long[] t2 = new long[N];

    void solve() {
        n = in.nextInt(); int Q = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = in.nextInt();
        int[] w = new int[n];
        for (int i = 0; i < n; i++) w[i] = in.nextInt();

        for (int i = 0; i < n; i++) a[i] -= i;

        for (int i = 0; i < n; i++) {
            add(t1, i, w[i]);
            add(t2, i, (long) a[i] * w[i] % MOD);
        }

        while (Q-- > 0) {
            int x = in.nextInt();
            if (x < 0) {
                int i = -x - 1, nw = in.nextInt();
                long delta1 = nw - w[i];
                long delta2 = (a[i] * nw % MOD - a[i] * w[i] % MOD + MOD) % MOD;
                w[i] = nw;
                add(t1, i, delta1);
                add(t2, i, delta2);
            } else {
                int l = x - 1, r = in.nextInt();
                long tot = sum(t1, l, r);
                int lb = l, ub = r;
                while (ub - lb > 1) {
                    int m = (lb + ub) >> 1;
                    if (sum(t1, l, m) * 2 <= tot) lb = m;
                    else ub = m;
                }
                int k = lb;
                long ans = norm(mul(a[k], nsum(t1, l, k)) - nsum(t2, l, k));
                ans = norm(ans + norm(nsum(t2, k + 1, r) - mul(a[k], nsum(t1, k + 1, r))));
                out.println(ans);
            }
        }
    }

    long nsum(long[] t, int l, int r) {
        return norm(sum(t, r - 1) - sum(t, l - 1));
    }

    long sum(long[] t, int l, int r) {
        return sum(t, r - 1) - sum(t, l - 1);
    }

    long sum(long[] t, int i) {
        long res = 0;
        for (int x = i; x >= 0; x = (x & x + 1) - 1) res += t[x];
        return res;
    }

    void add(long[] t, int i, long delta) {
        for (int x = i; x < n; x = x | x + 1) t[x] += delta;
    }

    long mul(long a, long b) {
        return a * b % MOD;
    }

    long norm(long a) {
        a %= MOD;
        if (a > MOD) a -= MOD;
        if (a < 0) a += MOD;
        return a;
    }

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

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

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

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

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

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

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


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

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

    int N = (int) 2e5 + 10;
    int MOD = (int) 1e9 + 7;
    int INF = (int) 2e9;

    int n;
    long[] t1 = new long[N << 2];
    long[] t2 = new long[N << 2];

    void solve() {
        n = in.nextInt(); int Q = in.nextInt();
        long[] a = new long[n];
        for (int i = 0; i < n; i++) a[i] = in.nextInt();
        long[] w = new long[n];
        for (int i = 0; i < n; i++) w[i] = in.nextInt();

        for (int i = 0; i < n; i++) a[i] -= i;

        long[] aw = new long[n];
        for (int i = 0; i < n; i++) aw[i] = mul(a[i], w[i]);

        build(t1, 0, 0, n, w);
        build(t2, 0, 0, n, aw);

        while (Q-- > 0) {
            int x = in.nextInt();
            if (x < 0) {
                int i = -x - 1, nw = in.nextInt();
                update(t1, 0, 0, n, i, nw);
                update(t2, 0, 0, n, i, mul(a[i], nw));
            } else {
                int l = x - 1, r = in.nextInt();
                long tot = query(t1, 0, 0, n, l, r);
                int k = (int) find(t1, 0, 0, n, l, r, tot / 2)[0];
                long ans = norm(mul(a[k], norm(query(t1, 0, 0, n, l, k))) - norm(query(t2, 0, 0, n, l, k)));
                ans = norm(ans + norm(norm(query(t2, 0, 0, n, k + 1, r)) - mul(a[k], norm(query(t1, 0, 0, n, k + 1, r)))));
                out.println(ans);
            }
        }
    }

    long[] find(long[] t, int k, int l, int r, int a, int b, long val) {
        if (l == a && r == b) {
            if (t[k] <= val) return new long[]{INF, t[k]};
            if (r - l == 1) return new long[]{l, t[l]};
        }
        int m = (l + r) >> 1;
        long pos = INF, sum = 0;
        if (a < m) {
            long[] ret = find(t, 2 * k + 1, l, m, a, Math.min(m, b), val);
            pos = Math.min(pos, ret[0]);
            sum += ret[1];
        }
        if (pos == INF && b >= m) {
            long[] ret = find(t, 2 * k + 2, m, r, Math.max(m, a), b, val - sum);
            pos = Math.min(pos, ret[0]);
            sum += ret[1];
        }
        return new long[]{pos, sum};
    }

    long query(long[] t, int k, int l, int r, int a, int b) {
        if (a <= l && r <= b) return t[k];
        if (a >= r || b <= l) return 0;
        int m = (l + r) >> 1;
        return query(t, 2 * k + 1, l, m, a, b) + query(t, 2 * k + 2, m, r, a, b);
    }

    void update(long[] t, int k, int l, int r, int i, long val) {
        if (r - l == 1) {
            t[k] = val;
            return;
        }
        int m = (l + r) >> 1;
        if (i < m) update(t, 2 * k + 1, l, m, i, val);
        else update(t, 2 * k + 2, m, r, i, val);
        t[k] = t[2 * k + 1] + t[2 * k + 2];
    }

    void build(long[] t, int k, int l, int r, long[] x) {
        if (r - l == 1) {
            t[k] = x[l];
            return;
        }
        int m = (l + r) >> 1;
        build(t, 2 * k + 1, l, m, x);
        build(t, 2 * k + 2, m, r, x);
        t[k] = t[2 * k + 1] + t[2 * k + 2];
    }

    long mul(long a, long b) {
        return a * b % MOD;
    }

    long norm(long a) {
        a %= MOD;
        if (a > MOD) a -= MOD;
        if (a < 0) a += MOD;
        return a;
    }

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

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

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

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

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

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

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


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

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

    int N = (int) 2e5 + 10;
    int MOD = (int) 1e9 + 7;

    int n;
    long[] t1 = new long[N];
    long[] t2 = new long[N];

    void solve() {
        n = in.nextInt(); int Q = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = in.nextInt();
        int[] w = new int[n];
        for (int i = 0; i < n; i++) w[i] = in.nextInt();

        for (int i = 0; i < n; i++) a[i] -= i;

        for (int i = 0; i < n; i++) {
            add(t1, i, w[i]);
            add(t2, i, (long) a[i] * w[i] % MOD);
        }

        while (Q-- > 0) {
            int x = in.nextInt();
            if (x < 0) {
                int i = -x - 1, nw = in.nextInt();
                long delta1 = nw - w[i];
                long delta2 = mul(a[i], nw) - mul(a[i], w[i]);
                w[i] = nw;
                add(t1, i, delta1);
                add(t2, i, delta2);
            } else {
                int l = x - 1, r = in.nextInt();
                long tot = sum(t1, l, r);
                int lb = l, ub = r;
                while (ub - lb > 1) {
                    int m = (lb + ub) >> 1;
                    if (sum(t1, l, m) * 2 <= tot) lb = m;
                    else ub = m;
                }
                int k = lb;
                long ans = norm(mul(a[k], nsum(t1, l, k)) - nsum(t2, l, k));
                ans = norm(ans + norm(nsum(t2, k + 1, r) - mul(a[k], nsum(t1, k + 1, r))));
                out.println(ans);
            }
        }
    }

    long nsum(long[] t, int l, int r) {
        return norm(sum(t, r - 1) - sum(t, l - 1));
    }

    long sum(long[] t, int l, int r) {
        return sum(t, r - 1) - sum(t, l - 1);
    }

    long sum(long[] t, int i) {
        long res = 0;
        for (int x = i; x >= 0; x = (x & x + 1) - 1) res += t[x];
        return res;
    }

    void add(long[] t, int i, long delta) {
        for (int x = i; x < n; x = x | x + 1) t[x] += delta;
    }

    long mul(long a, long b) {
        return a * b % MOD;
    }

    long norm(long a) {
        a %= MOD;
        if (a > MOD) a -= MOD;
        if (a < 0) a += MOD;
        return a;
    }

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

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

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

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

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

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

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


import java.util.*;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.*;

import javax.swing.plaf.SliderUI;

import static java.lang.Math.*;

public class Solution implements Runnable {

	ArrayList<Integer> g [];
	ArrayList<Integer> topoSort = new ArrayList<>();

	int vars[];
	int topIndex [];
	int color [];
	int variables[];

	boolean used [];

	boolean findCycle(int v) {
		if (color[v] == 2)
			return false;
		if (color[v] == 1)
			return true;
		color[v] = 1;
		for (int i = 0; i < g[v].size(); i++)
			if (findCycle(g[v].get(i)))
				return true;
		color[v] = 2;
		return false;
	}

	void dfs(int v) {
		if (used[v])
			return;
		used[v] = true;
		variables[v] = 0;
		for (int i = 0; i < g[v].size(); i++) {
			dfs(g[v].get(i));
		}
		topoSort.add(v);
	}

	void findDivisonByZeroTypes(Node node) {
		if (node instanceof OperationNode) {
			OperationNode opNode = (OperationNode) node;
			VariableNode right = (VariableNode) opNode.right;
			if (opNode.operation == '/') {
				variables[right.variableType] = 1;
			}
			findDivisonByZeroTypes(opNode.left);
			findDivisonByZeroTypes(opNode.right);
		} else {
			return;
		}
	}

	interface Node {

		long eval (int[] variables);

	}

	class VariableNode implements Node {

		int variableIndex;
		int variableType;

		public VariableNode(int variableIndex, int variableType) {
			this.variableIndex = variableIndex;
			this.variableType = variableType;
		}

		@Override
		public long eval(int[] variables) {
			return variables[variableIndex];
		}

	}

	class OperationNode implements Node {

		char operation;
		Node left, right;

		public OperationNode(Node left, Node right, char operation) {
			this.left = left;
			this.right = right;
			this.operation = operation;
		}

		@Override
		public long eval(int[] variables) {
			long l = left.eval(variables);
			long r = right.eval(variables);
			switch (operation) {
				case '+':
					return l + r;
				case '-':
					return l - r;
				case '*':
					return l * r;
				case '/':
					return l / r;
			}
			return 0;
		}

	}

	class Parser {

		int it;
		String expression;

		int operationPriority[] = new int [256];

		int variables;
		ArrayList<Integer> variableTypes = new ArrayList<>();

		public Parser() {
			operationPriority['-'] = operationPriority['+'] = 0;
			operationPriority['*'] = operationPriority['/'] = 1;
		}

		public Parser(String expression) {
			super();
			this.expression = expression;
		}

		public Node parse() {
			it = 0;
			return parse(0);
		}

		public int[] getVars() {
			int[] vars = new int [variables];
			for (int i = 0; i < variables; i++) {
				vars[i] = variableTypes.get(i);
			}
			return vars;
		}

		private Node parseValue() {
			int variableType = 0;
			while (it < expression.length() && expression.charAt(it) == '_') {
				variableType++;
				it++;
			}
			variables++;
			variableTypes.add(variableType);
			return new VariableNode(variables - 1, variableType);
		}

		private Node parse(int prior) {
			if (prior == 2)
				return parseValue();
			Node result = parse(prior + 1);
			while (it < expression.length() && operationPriority[expression.charAt(it)] == prior) {
				char operation = expression.charAt(it);
				it++;
				Node right = parse(prior + 1);
				result = new OperationNode(result, right, operation);
			}
			return result;
		}

	}

	public void solve() throws Exception {
		color = new int [1024];
		g = new ArrayList[1024];
		for (int i = 0; i < 1024; i++)
			g[i] = new ArrayList<>();

		String a = sc.nextToken();
		StringBuilder sb = new StringBuilder();

		int lBracket = a.indexOf('(');
		int rBracket = a.indexOf(')');

		String expression = a.substring(lBracket + 1, rBracket);
		Parser parser = new Parser(expression);

		Node root = parser.parse();

		vars = parser.getVars();
		Integer varIndices[] = new Integer [vars.length];
		for (int i = 0; i < vars.length; i++)
			varIndices[i] = i;

		boolean usedTypes [] = new boolean[1024];
		for (int i = 0; i < vars.length; i++) {
			usedTypes[vars[i]] = true;
		}

		int colon = a.indexOf(":-");
		String inequalityString = a.substring(colon + 2, a.length() - 1);
		String[] inequalities = inequalityString.split(",");
		for (String inequality : inequalities) {
			char separator;
			int separatorIndex = -1;
			if (inequality.indexOf('>') != -1) {
				separator = '>';
				separatorIndex = inequality.indexOf('>');
			} else {
				separator = '<';
				separatorIndex = inequality.indexOf('<');
			}
			int typeLeft = separatorIndex;
			int typeRight = inequality.length() - separatorIndex - 1;
			if (separator == '>') {
				g[typeLeft].add(typeRight);
			} else {
				g[typeRight].add(typeLeft);
			}
		}

		for (int i = 0; i < 1024; i++) {
			if (color[i] == 0) {
				if (findCycle(i)) {
					out.println("false");
					return;
				}
			}
		}

		variables = new int [1024];
		used = new boolean [1024];
		Arrays.fill(variables, -1);
		for (int i = 0; i < 1024; i++) {
			if (usedTypes[i]) {
				dfs(i);
			}
		}

		findDivisonByZeroTypes(root);

		for (int type : topoSort) {
			int maxValue = 0;
			for (int to : g[type]) {
				maxValue = max (maxValue, variables[to] + 1);
			}
			variables[type] = maxValue;
			if (variables[type] > 9) {
				out.println("false");
				return;
			}
		}

		for (int i = 0; i < vars.length; i++) {
			out.print(variables[vars[i]]);
		}

	}

	static Throwable t;

	BufferedReader in;
	FastScanner sc;
	PrintWriter out;

	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			sc = new FastScanner(in);
			solve();
		} catch (Throwable t) {
			Solution.t = t;
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) throws Throwable {
		Thread thread = new Thread(null, new Solution(), "", 1 << 26);
		thread.start();
		thread.join();
		if (Solution.t != null)
			throw t;
	}

}

class FastScanner {

	BufferedReader in;
	StringTokenizer st;

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

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

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

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

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

}


import java.util.*;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.*;

import javax.swing.plaf.SliderUI;

import static java.lang.Math.*;

public class Solution implements Runnable {

	ArrayList<Integer> g [];
	ArrayList<Integer> topoSort = new ArrayList<>();

	int vars[];
	int topIndex [];
	int color [];
	int variables[];

	boolean used [];

	boolean findCycle(int v) {
		if (color[v] == 2)
			return false;
		if (color[v] == 1)
			return true;
		color[v] = 1;
		for (int i = 0; i < g[v].size(); i++)
			if (findCycle(g[v].get(i)))
				return true;
		color[v] = 2;
		return false;
	}

	void dfs(int v) {
		if (used[v])
			return;
		used[v] = true;
		variables[v] = 0;
		for (int i = 0; i < g[v].size(); i++) {
			dfs(g[v].get(i));
		}
		topoSort.add(v);
	}

	void findDivisonByZeroTypes(Node node) {
		if (node instanceof OperationNode) {
			OperationNode opNode = (OperationNode) node;
			VariableNode right = (VariableNode) opNode.right;
			if (opNode.operation == '/') {
				variables[right.variableType] = 1;
			}
		} else {
			return;
		}
	}

	interface Node {

		long eval (int[] variables);

	}

	class VariableNode implements Node {

		int variableIndex;
		int variableType;

		public VariableNode(int variableIndex, int variableType) {
			this.variableIndex = variableIndex;
			this.variableType = variableType;
		}

		@Override
		public long eval(int[] variables) {
			return variables[variableIndex];
		}

	}

	class OperationNode implements Node {

		char operation;
		Node left, right;

		public OperationNode(Node left, Node right, char operation) {
			this.left = left;
			this.right = right;
			this.operation = operation;
		}

		@Override
		public long eval(int[] variables) {
			long l = left.eval(variables);
			long r = right.eval(variables);
			switch (operation) {
				case '+':
					return l + r;
				case '-':
					return l - r;
				case '*':
					return l * r;
				case '/':
					return l / r;
			}
			return 0;
		}

	}

	class Parser {

		int it;
		String expression;

		int operationPriority[] = new int [256];

		int variables;
		ArrayList<Integer> variableTypes = new ArrayList<>();

		public Parser() {
			operationPriority['-'] = operationPriority['+'] = 0;
			operationPriority['*'] = operationPriority['/'] = 1;
		}

		public Parser(String expression) {
			super();
			this.expression = expression;
		}

		public Node parse() {
			it = 0;
			return parse(0);
		}

		public int[] getVars() {
			int[] vars = new int [variables];
			for (int i = 0; i < variables; i++) {
				vars[i] = variableTypes.get(i);
			}
			return vars;
		}

		private Node parseValue() {
			int variableType = 0;
			while (it < expression.length() && expression.charAt(it) == '_') {
				variableType++;
				it++;
			}
			variables++;
			variableTypes.add(variableType);
			return new VariableNode(variables - 1, variableType);
		}

		private Node parse(int prior) {
			if (prior == 2)
				return parseValue();
			Node result = parse(prior + 1);
			while (it < expression.length() && operationPriority[expression.charAt(it)] == prior) {
				char operation = expression.charAt(it);
				it++;
				Node right = parse(prior + 1);
				result = new OperationNode(result, right, operation);
			}
			return result;
		}

	}

	public void solve() throws Exception {
		color = new int [1024];
		g = new ArrayList[1024];
		for (int i = 0; i < 1024; i++)
			g[i] = new ArrayList<>();

		String a = sc.nextToken();
		StringBuilder sb = new StringBuilder();

		int lBracket = a.indexOf('(');
		int rBracket = a.indexOf(')');

		String expression = a.substring(lBracket + 1, rBracket);
		Parser parser = new Parser(expression);

		Node root = parser.parse();

		vars = parser.getVars();
		Integer varIndices[] = new Integer [vars.length];
		for (int i = 0; i < vars.length; i++)
			varIndices[i] = i;

		boolean usedTypes [] = new boolean[1024];
		for (int i = 0; i < vars.length; i++) {
			usedTypes[vars[i]] = true;
		}

		int colon = a.indexOf(":-");
		String inequalityString = a.substring(colon + 2, a.length() - 1);
		String[] inequalities = inequalityString.split(",");
		for (String inequality : inequalities) {
			char separator;
			int separatorIndex = -1;
			if (inequality.indexOf('>') != -1) {
				separator = '>';
				separatorIndex = inequality.indexOf('>');
			} else {
				separator = '<';
				separatorIndex = inequality.indexOf('<');
			}
			int typeLeft = separatorIndex;
			int typeRight = inequality.length() - separatorIndex - 1;
			if (separator == '>') {
				g[typeLeft].add(typeRight);
			} else {
				g[typeRight].add(typeLeft);
			}
		}

		for (int i = 0; i < 1024; i++) {
			if (color[i] == 0) {
				if (findCycle(i)) {
					out.println("false");
					return;
				}
			}
		}

		variables = new int [1024];
		used = new boolean [1024];
		Arrays.fill(variables, -1);
		for (int i = 0; i < 1024; i++) {
			if (usedTypes[i]) {
				dfs(i);
			}
		}

		for (int type : topoSort) {
			int maxValue = 0;
			for (int to : g[type]) {
				maxValue = max (maxValue, variables[to] + 1);
			}
			variables[type] = maxValue;
			if (variables[type] > 9) {
				out.println("false");
				return;
			}
		}

		for (int i = 0; i < vars.length; i++) {
			out.print(variables[vars[i]]);
		}

	}

	static Throwable t;

	BufferedReader in;
	FastScanner sc;
	PrintWriter out;

	@Override
	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			sc = new FastScanner(in);
			solve();
		} catch (Throwable t) {
			Solution.t = t;
		} finally {
			out.close();
		}
	}

	public static void main(String[] args) throws Throwable {
		Thread thread = new Thread(null, new Solution(), "", 1 << 26);
		thread.start();
		thread.join();
		if (Solution.t != null)
			throw t;
	}

}

class FastScanner {

	BufferedReader in;
	StringTokenizer st;

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

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

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

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

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

}


import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

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

public class G {

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	static int n, nn;
	static long edges[][];
	static int matchingL[], matchingR[];

	static int hopcroftKarpDist[];

	static int hopcroftKarp() {
		fill(matchingL, -1);
		fill(matchingR, -1);
		int queue[] = new int[2 * n];
		int size = 0;
		while (true) {
			fill(hopcroftKarpDist, -1);
			int queueHead = 0, queueTail = 0;
			for (int i = 0; i < n; i++) {
				if (matchingL[i] < 0) {
					queue[queueTail++] = i;
					queue[queueTail++] = 0;
				}
			}
			int resDist = -1;
			while (queueHead < queueTail) {
				int cur = queue[queueHead++];
				int cdist = queue[queueHead++];
				if ((cdist + Integer.MIN_VALUE) > (resDist + Integer.MIN_VALUE)) {
					break;
				}
				for (int nextBase = 0; nextBase < nn; nextBase++) {
					long v = edges[cur][nextBase];
					if (v != 0) {
						for (int next = nextBase << 6; next < (nextBase + 1) << 6; next++) {
							if ((v & (1L << next)) == 0 || hopcroftKarpDist[next] != -1) {
								continue;
							}
							hopcroftKarpDist[next] = cdist;
							int next2 = matchingR[next];
							if (next2 < 0) {
								resDist = cdist;
							} else {
								queue[queueTail++] = next2;
								queue[queueTail++] = cdist + 1;
							}
						}
					}
				}
			}
			if (resDist == -1) {
				return size;
			}
			for (int i = 0; i < n; i++) {
				if (matchingL[i] < 0 && hopcroftKarpDfs(i, 0)) {
					++size;
				}
			}
		}
	}

	static boolean hopcroftKarpDfs(int cur, int cdist) {
		for (int nextBase = 0; nextBase < nn; nextBase++) {
			long v = edges[cur][nextBase];
			if (v != 0) {
				for (int next = nextBase << 6; next < (nextBase + 1) << 6; next++) {
					if ((v & (1L << next)) == 0 || hopcroftKarpDist[next] != cdist) {
						continue;
					}
					hopcroftKarpDist[next] = -1;
					int next2 = matchingR[next];
					if (next2 < 0 || hopcroftKarpDfs(next2, cdist + 1)) {
						matchingR[next] = cur;
						matchingL[cur] = next;
						return true;
					}
				}
			}
		}
		return false;
	}

	static void solve() throws Exception {
		n = nextInt();
		int q = nextInt();
//		n = 10000;
//		int q = 10000;
		nn = (n >> 6) + 1;
		edges = new long[n][nn];
		for (int x = 0; x < n; x++) {
			for (int y = 0; y < n >> 6; y++) {
				edges[x][y] = -1L;
			}
			edges[x][n >> 6] = (1L << n) - 1;
		}
		for (int i = 0; i < q; i++) {
			int x1 = nextInt() - 1;
			int y1 = nextInt() - 1;
			int x2 = nextInt();
			int y2 = nextInt();
//			int x1 = 9999 - i, x2 = 10000, y1 = i, y2 = i + 1;
			if (y1 >> 6 == y2 >> 6) {
				long mask = ~((1L << y2) - (1L << y1));
				for (int x = x1; x < x2; x++) {
					edges[x][y1 >> 6] &= mask;
				}
			} else {
				for (int x = x1; x < x2; x++) {
					edges[x][y1 >> 6] &= ~(-1L << y1);
					for (int y = (y1 >> 6) + 1; y < y2 >> 6; y++) {
						edges[x][y] = 0;
					}
					edges[x][y2 >> 6] &= -1L << y2;
				}
			}
		}
		hopcroftKarpDist = new int[n];
		matchingL = new int[n];
		matchingR = new int[n];
		out.print(hopcroftKarp());
	}

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

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

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

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

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(new OutputStreamWriter(System.out));
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

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

public class GFast {

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	static int n, len;
	static long edges[][];
	static int matchingL[], matchingR[];
	static int hkQueue[];
	static long hkSet[], hkSet2[][];

	static final int BIT_INDEX[] = {
		0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 34, 20, 40,
		5, 17, 26, 38, 15, 46, 29, 48, 10, 31, 35, 54, 21, 50, 41, 57,
		63, 6, 12, 18, 24, 27, 33, 39, 16, 37, 45, 47, 30, 53, 49, 56,
		62, 11, 23, 32, 36, 44, 52, 55, 61, 22, 43, 51, 60, 42, 59, 58};

	static int bitIndex(long x) {
		return BIT_INDEX[(int) ((x * 0x218a392cd3d5dbfL) >>> 58)];
	}

	static int hopcroftKarp() {
		fill(matchingL, -1);
		fill(matchingR, -1);
		int size = 0;
		while (true) {
			fill(hkSet, -1L);
			int queueHead = 0, queueTail = 0;
			for (int i = 0; i < n; i++) {
				if (matchingL[i] < 0) {
					hkQueue[queueTail++] = i;
					hkQueue[queueTail++] = 0;
				}
			}
			int resDist = -1;
			while (queueHead < queueTail) {
				int cur = hkQueue[queueHead++];
				int cdist = hkQueue[queueHead++];
				if ((cdist + Integer.MIN_VALUE) > (resDist + Integer.MIN_VALUE)) {
					break;
				}
				long ecur[] = edges[cur], curSet2[] = hkSet2[cdist];
				for (int nextBlock = 0; nextBlock < len; nextBlock++) {
					long v = hkSet[nextBlock], w = ecur[nextBlock] & v;
					if (w == 0) {
						continue;
					}
					hkSet[nextBlock] = v ^ w;
					curSet2[nextBlock] |= w;
					do {
						long x = w & -w;
						w ^= x;
						int next = (nextBlock << 6) + bitIndex(x);
						int next2 = matchingR[next];
						if (next2 < 0) {
							resDist = cdist;
						} else {
							hkQueue[queueTail++] = next2;
							hkQueue[queueTail++] = cdist + 1;
						}
					} while (w != 0);
				}
			}
			if (resDist == -1) {
				return size;
			}
			for (int i = 0; i < n; i++) {
				if (matchingL[i] < 0 && hopcroftKarpDfs(i, 0)) {
					++size;
				}
			}
			for (int i = 0; i <= resDist; i++) {
				fill(hkSet2[i], 0);
			}
		}
	}

	static boolean hopcroftKarpDfs(int cur, int cdist) {
		long ecur[] = edges[cur], curSet2[] = hkSet2[cdist];
		for (int nextBlock = 0; nextBlock < len; nextBlock++) {
			long v = curSet2[nextBlock], w = ecur[nextBlock] & v;
			if (w == 0) {
				continue;
			}
			v ^= w;
			do {
				long x = w & -w;
				w ^= x;
				int next = (nextBlock << 6) + bitIndex(x);
				int next2 = matchingR[next];
				if (next2 < 0 || hopcroftKarpDfs(next2, cdist + 1)) {
					matchingR[next] = cur;
					matchingL[cur] = next;
					curSet2[nextBlock] = v ^ w;
					return true;
				}
			} while (w != 0);
			curSet2[nextBlock] = v;
		}
		return false;
	}

	static void solve() throws Exception {
		n = nextInt();
		int q = nextInt();
		len = (n + 63) >> 6;
		edges = new long[n][len];
		matchingL = new int[n];
		matchingR = new int[n];
		hkQueue = new int[2 * n];
		hkSet = new long[len];
		hkSet2 = new long[n][len];
		for (int x = 0; x < n; x++) {
			for (int y = 0; y < n >> 6; y++) {
				edges[x][y] = -1L;
			}
			if ((n & 63) != 0) {
				edges[x][n >> 6] = (1L << n) - 1;
			}
		}
		for (int i = 0; i < q; i++) {
			int x1 = nextInt() - 1;
			int y1 = nextInt() - 1;
			int x2 = nextInt();
			int y2 = nextInt();
			if (y1 >> 6 == y2 >> 6) {
				long mask = ~((1L << y2) - (1L << y1));
				for (int x = x1; x < x2; x++) {
					edges[x][y1 >> 6] &= mask;
				}
			} else {
				for (int x = x1; x < x2; x++) {
					edges[x][y1 >> 6] &= ~(-1L << y1);
					for (int y = (y1 >> 6) + 1; y < y2 >> 6; y++) {
						edges[x][y] = 0;
					}
					if ((y2 & 63) != 0) {
						edges[x][y2 >> 6] &= -1L << y2;
					}
				}
			}
		}
		out.print(hopcroftKarp());
	}

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

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

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

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

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(new OutputStreamWriter(System.out));
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

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

public class GFast {

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	static int n, len;
	static long edges[][];
	static int matchingL[], matchingR[];
	static int hkQueue[];
	static long hkSet[], hkSet2[][];

	static final int BIT_INDEX[] = {
		0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 34, 20, 40,
		5, 17, 26, 38, 15, 46, 29, 48, 10, 31, 35, 54, 21, 50, 41, 57,
		63, 6, 12, 8, 24, 27, 33, 39, 16, 37, 45, 47, 30, 53, 49, 56,
		62, 11, 23, 32, 36, 44, 52, 55, 61, 22, 43, 51, 60, 42, 59, 58};

	static int bitIndex(long x) {
		return BIT_INDEX[(int) ((x * 0x218a392cd3d5dbfL) >>> 58)];
	}

	static int hopcroftKarp() {
		fill(matchingL, -1);
		fill(matchingR, -1);
		int size = 0;
		while (true) {
			fill(hkSet, -1L);
			int queueHead = 0, queueTail = 0;
			for (int i = 0; i < n; i++) {
				if (matchingL[i] < 0) {
					hkQueue[queueTail++] = i;
					hkQueue[queueTail++] = 0;
				}
			}
			int resDist = -1;
			while (queueHead < queueTail) {
				int cur = hkQueue[queueHead++];
				int cdist = hkQueue[queueHead++];
				if ((cdist + Integer.MIN_VALUE) > (resDist + Integer.MIN_VALUE)) {
					break;
				}
				long ecur[] = edges[cur], curSet2[] = hkSet2[cdist];
				for (int nextBlock = 0; nextBlock < len; nextBlock++) {
					long v = hkSet[nextBlock], w = ecur[nextBlock] & v;
					if (w == 0) {
						continue;
					}
					hkSet[nextBlock] = v ^ w;
					curSet2[nextBlock] |= w;
					do {
						long x = w & -w;
						w ^= x;
						int next = (nextBlock << 6) + bitIndex(x);
						int next2 = matchingR[next];
						if (next2 < 0) {
							resDist = cdist;
						} else {
							hkQueue[queueTail++] = next2;
							hkQueue[queueTail++] = cdist + 1;
						}
					} while (w != 0);
				}
			}
			if (resDist == -1) {
				return size;
			}
			for (int i = 0; i < n; i++) {
				if (matchingL[i] < 0 && hopcroftKarpDfs(i, 0)) {
					++size;
				}
			}
			for (int i = 0; i <= resDist; i++) {
				fill(hkSet2[i], 0);
			}
		}
	}

	static boolean hopcroftKarpDfs(int cur, int cdist) {
		long ecur[] = edges[cur], curSet2[] = hkSet2[cdist];
		for (int nextBlock = 0; nextBlock < len; nextBlock++) {
			long v = curSet2[nextBlock], w = ecur[nextBlock] & v;
			if (w == 0) {
				continue;
			}
			v ^= w;
			do {
				long x = w & -w;
				w ^= x;
				int next = (nextBlock << 6) + bitIndex(x);
				int next2 = matchingR[next];
				if (next2 < 0 || hopcroftKarpDfs(next2, cdist + 1)) {
					matchingR[next] = cur;
					matchingL[cur] = next;
					curSet2[nextBlock] = v ^ w;
					return true;
				}
			} while (w != 0);
			curSet2[nextBlock] = v;
		}
		return false;
	}

	static void solve() throws Exception {
		n = nextInt();
		int q = nextInt();
		len = (n + 63) >> 6;
		edges = new long[n][len];
		matchingL = new int[n];
		matchingR = new int[n];
		hkQueue = new int[2 * n];
		hkSet = new long[len];
		hkSet2 = new long[n][len];
		for (int x = 0; x < n; x++) {
			for (int y = 0; y < n >> 6; y++) {
				edges[x][y] = -1L;
			}
			if ((n & 63) != 0) {
				edges[x][n >> 6] = (1L << n) - 1;
			}
		}
		for (int i = 0; i < q; i++) {
			int x1 = nextInt() - 1;
			int y1 = nextInt() - 1;
			int x2 = nextInt();
			int y2 = nextInt();
			if (y1 >> 6 == y2 >> 6) {
				long mask = ~((1L << y2) - (1L << y1));
				for (int x = x1; x < x2; x++) {
					edges[x][y1 >> 6] &= mask;
				}
			} else {
				for (int x = x1; x < x2; x++) {
					edges[x][y1 >> 6] &= ~(-1L << y1);
					for (int y = (y1 >> 6) + 1; y < y2 >> 6; y++) {
						edges[x][y] = 0;
					}
					if ((y2 & 63) != 0) {
						edges[x][y2 >> 6] &= -1L << y2;
					}
				}
			}
		}
		out.print(hopcroftKarp());
	}

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

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

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

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

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(new OutputStreamWriter(System.out));
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


import java.util.*;
import java.io.*;
public class F {

	static long mod = 998244353;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();

		String[] s = new String[n];
		for(int i = 0; i < n; i++) {
			s[i] = sc.next();
		}

		HashSet<String> prefs = new HashSet<>();
		for(int i = 0; i < n; i++){
			for(int j = 1; j < s[i].length(); j++){
				prefs.add(s[i].substring(j));
			}
		}
		prefs.add("");
		HashSet<Pair> nodes = new HashSet<>();
		for(String a: prefs){
			for(String b: prefs){
				if(isPref(a, b)) {
					nodes.add(new Pair(a, b));
				}
			}
		}
		int N = nodes.size();
		HashMap<Pair, Integer> code = new HashMap<>();
		Pair[] decode = new Pair[N];
		int count = 0;
		for(Pair p: nodes) {
			decode[count] = p;
			code.put(p, count++);
		}
		long[][] aut = new long[N][N];
		Pair p0 = new Pair("","");
		for(String t: s) {
			for(String u: s) {
				if(isPref(t, u)) {
					String a = t.substring(1);
					String b = u.substring(1);
					Pair p = new Pair(a, b);
					aut[code.get(p0)][code.get(p)]++;
				}
			}
		}
		for(Pair p: nodes) {
			Pair q = next(p);
			if(p.equals(p0)){
				continue;
			}
			else if(q != null) {
				aut[code.get(p)][code.get(q)]++;
			}
			else {
				for(String t: s) {
					q = next(p, t);
					if(q != null && nodes.contains(q)) {
						aut[code.get(p)][code.get(q)]++;
					}
				}
			}
		}
		Matrix mat = new Matrix(aut);
		Matrix matp = pow(mat, m);
		System.out.println(matp.mat[code.get(p0)][code.get(p0)]);
	}
	static Pair next(Pair p, String s) {
		if(p.a.equals("")) {
			if(isPref(s, p.b)) {
				String a = s.substring(1);
				String b = p.b.substring(1);
				return new Pair(a, b);
			}
			else return null;
		}
		else if(p.b.equals("")) {
			if(isPref(s, p.a)) {
				String a = p.a.substring(1);
				String b = s.substring(1);
				return new Pair(a, b);
			}
			else return null;
		}
		else return null;
	}
	static Pair next(Pair p) {
		if(p.a.equals("")) return null;
		if(p.b.equals("")) return null;
		String a = p.a.substring(1);
		String b = p.b.substring(1);
		return new Pair(a, b);
	}
	static boolean isPref(String a, String b) {
		if(a.length() == b.length()) {
			return a.equals(b);
		}
		else if(a.length() > b.length()) {
			return b.equals(a.substring(0, b.length()));
		}
		else {
			return a.equals(b.substring(0, a.length()));
		}
	}
	static class Pair {
		String a, b;
		public Pair(String a, String b) {
			this.a = a; this.b = b;
		}
		@Override
		public int hashCode() {
			return a.hashCode() + b.hashCode();
		}
		@Override
		public boolean equals(Object o) {
			Pair p = (Pair)o;
			return a.equals(p.a) && b.equals(p.b);
		}
		public String toString() {
			return "'"+a+"' '"+b;
		}
	}

	static Matrix pow(Matrix m, int exp) {
		Matrix res = new Matrix(m.n);
		Matrix mapow = m;
		while(exp > 0) {
			if((exp & 1) == 1) {
				res = res.mult(mapow);
			}
			mapow = mapow.mult(mapow);
			exp >>= 1;
		}
		return res;
	}
	static class Matrix{
		long[][] mat; int n;
		public Matrix(long[][] mat) {
			n = mat.length;
			this.mat = mat;
		}
		public Matrix(int n) {
			mat = new long[n][n];
			this.n = n;
			for(int i = 0; i < n; i++) mat[i][i] = 1;
		}
		Matrix mult(Matrix m) {
			long[][] res = new long[n][n];
			for(int i = 0; i < n; i++) {
				for(int j = 0; j < n; j++) {
					long val = 0;
					for(int k = 0; k < n; k++) {
						val += mat[i][k] * m.mat[k][j] % mod;
						val %= mod;
					}
					res[i][j] = val;
				}
			}
			return new Matrix(res);
		}
		public String toString(){
			StringBuilder sb = new StringBuilder();
			for(int i = 0; i < n; i++) {
				sb.append(Arrays.toString(mat[i])+"\n");
			}
			return sb.toString();
		}
		long[] mult(long[] vec) {
			long[] res = new long[n];
			for(int i = 0; i < n; i++) {
				for(int j = 0; j < n; j++) {
					res[i] += vec[j] * mat[i][j] % mod;
					res[i] %= mod;
				}
			}
			return res;
		}
		long[] tmult(long[] vec) {
			long[] res = new long[n];
			for(int i = 0; i < n; i++) {
				for(int j = 0; j < n; j++) {
					res[j] += vec[i] * mat[i][j] % mod;
					res[j] %= mod;
				}
			}
			return res;
		}
	}

}


import java.util.*;
import java.io.*;
public class F {

	static long mod = 998244353;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();

		String[] s = new String[n];
		for(int i = 0; i < n; i++) {
			s[i] = sc.next();
		}

		HashSet<String> prefs = new HashSet<>();
		for(int i = 0; i < n; i++){
			for(int j = 1; j < s[i].length(); j++){
				prefs.add(s[i].substring(j));
			}
		}
		prefs.add("");
		HashSet<Pair> nodes = new HashSet<>();
		for(String a: prefs){
			for(String b: prefs){
				if(isPref(a, b)) {
					nodes.add(new Pair(a, b));
				}
			}
		}
		int N = nodes.size();
		HashMap<Pair, Integer> code = new HashMap<>();
		Pair[] decode = new Pair[N];
		int count = 0;
		for(Pair p: nodes) {
			decode[count] = p;
			code.put(p, count++);
		}
		long[][] aut = new long[N][N];
		Pair p0 = new Pair("","");
		for(String t: s) {
			for(String u: s) {
				if(isPref(t, u)) {
					String a = t.substring(1);
					String b = u.substring(1);
					Pair p = new Pair(a, b);
					aut[code.get(p0)][code.get(p)]++;
				}
			}
		}
		for(Pair p: nodes) {
			Pair q = next(p);
			if(p.equals(p0)){
				continue;
			}
			else if(q != null) {
				aut[code.get(p)][code.get(q)]++;
			}
			else {
				for(String t: s) {
					q = next(p, t);
					if(q != null && nodes.contains(q)) {
						aut[code.get(p)][code.get(q)]++;
					}
				}
			}
		}
		Matrix mat = new Matrix(aut);
		Matrix matp = pow(mat, m);
		System.out.println(matp.mat[code.get(p0)][code.get(p0)]);
	}
	static Pair next(Pair p, String s) {
		if(p.a.equals("")) {
			if(isPref(s, p.b)) {
				String a = s.substring(1);
				String b = p.b.substring(1);
				return new Pair(a, b);
			}
			else return null;
		}
		else if(p.b.equals("")) {
			if(isPref(s, p.a)) {
				String a = p.a.substring(1);
				String b = s.substring(1);
				return new Pair(a, b);
			}
			else return null;
		}
		else return null;
	}
	static Pair next(Pair p) {
		if(p.a.equals("")) return null;
		if(p.b.equals("")) return null;
		String a = p.a.substring(1);
		String b = p.b.substring(1);
		return new Pair(a, b);
	}
	static boolean isPref(String a, String b) {
		if(a.length() == b.length()) {
			return a.equals(b);
		}
		else if(a.length() > b.length()) {
			return b.equals(a.substring(0, b.length()));
		}
		else {
			return a.equals(b.substring(0, a.length()));
		}
	}
	static class Pair {
		String a, b;
		public Pair(String a, String b) {
			this.a = a; this.b = b;
		}
		@Override
		public int hashCode() {
			return a.hashCode() + b.hashCode();
		}
		@Override
		public boolean equals(Object o) {
			Pair p = (Pair)o;
			return a.equals(p.a) && b.equals(p.b);
		}
		public String toString() {
			return "'"+a+"' '"+b;
		}
	}

	static Matrix pow(Matrix m, int exp) {
		Matrix res = new Matrix(m.n);
		Matrix mapow = m;
		while(exp > 0) {
			if((exp & 1) == 1) {
				res = res.mult(mapow);
			}
			mapow = mapow.mult(mapow);
			exp >>= 1;
		}
		return res;
	}
	static class Matrix{
		long[][] mat; int n;
		public Matrix(long[][] mat) {
			n = mat.length;
			this.mat = mat;
		}
		public Matrix(int n) {
			mat = new long[n][n];
			this.n = n;
			for(int i = 0; i < n; i++) mat[i][i] = 1;
		}
		Matrix mult(Matrix m) {
			long[][] res = new long[n][n];
			for(int k = 0; k < n; k++) {
				for(int i = 0; i < n; i++) {
					for(int j = 0; j < n; j++) {
						res[i][j] += mat[i][k] * m.mat[k][j] % mod;
						res[i][j] %= mod;
					}
				}
			}
			return new Matrix(res);
		}
		public String toString(){
			StringBuilder sb = new StringBuilder();
			for(int i = 0; i < n; i++) {
				sb.append(Arrays.toString(mat[i])+"\n");
			}
			return sb.toString();
		}
		long[] mult(long[] vec) {
			long[] res = new long[n];
			for(int i = 0; i < n; i++) {
				for(int j = 0; j < n; j++) {
					res[i] += vec[j] * mat[i][j] % mod;
					res[i] %= mod;
				}
			}
			return res;
		}
		long[] tmult(long[] vec) {
			long[] res = new long[n];
			for(int i = 0; i < n; i++) {
				for(int j = 0; j < n; j++) {
					res[j] += vec[i] * mat[i][j] % mod;
					res[j] %= mod;
				}
			}
			return res;
		}
	}

}


//package ecr107;

import java.io.*;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Queue;

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

	void solve()
	{
		int n = ni(), m = ni();
		char[][] ss = new char[n][];
		String[] oss = new String[n];
		for(int i = 0;i < n;i++){
			ss[i] = ns().toCharArray();
			oss[i] = new String(ss[i]);
		}
		int[] offset = new int[n+1];
		offset[0] = 1;
		for(int i = 0;i < n;i++){
			offset[i+1] = offset[i] + ss[i].length-1;
		}
		int U = offset[n]-1;

		final int D = 5;
		int[][] M = new int[(2*U+1)*D][(2*U+1)*D];
//		tr(offset);
		for(int i = 0;i < 2*U+1;i++){
			int lb, of;
			if(i == 0) {
				lb = 0;
				of = 0;
			}else if(i < U+1) {
				lb = lowerBound(offset, i+1) - 1;
				of = i-offset[lb] + 1;
			}else {
				lb = lowerBound(offset, i-U + 1) - 1;
				of = i - U - offset[lb] + 1;
			}
//			tr(i, lb, of, U);

			if(i == 0){
				for(int j = 0;j < n;j++){
					for(int k = 0;k < n;k++){
						if(k != j && oss[k].startsWith(oss[j])){
							M[offset[k]+ss[j].length-1][0+(2*U+1)*(ss[j].length-1)] = 1;
							M[offset[k]+U+ss[j].length-1][0+(2*U+1)*(ss[j].length-1)] = 1;
						}
					}
					M[0][0+(2*U+1)*(ss[j].length-1)] += 1;
				}
			}else if(i < U+1){
				// r: 0 -> 0
				for(int j = 0;j < n;j++){
					if(oss[lb].substring(of).equals(oss[j])){
						M[0][i+(2*U+1)*(oss[j].length()-1)] += 1;
					}else if(oss[lb].substring(of).startsWith(oss[j])){
						M[i+oss[j].length()][i+(2*U+1)*(oss[j].length()-1)] += 1;
					}
				}
				// l: -> 0
				String suf = oss[lb].substring(of);
				for(int j = 0;j < n;j++){
					if(oss[j].startsWith(suf) && !oss[j].equals(suf)){
						M[U+offset[j]+suf.length()-1][i+(2*U+1)*(suf.length()-1)] += 1;
					}
				}
			}else{
				// l: 0 -> 0
				for(int j = 0;j < n;j++){
					if(oss[lb].substring(of).equals(oss[j])){
						M[0][i+(2*U+1)*(oss[j].length()-1)] += 1;
					}else if(oss[lb].substring(of).startsWith(oss[j])){
						M[i+oss[j].length()][i+(2*U+1)*(oss[j].length()-1)] += 1;
					}
				}
				// r: -> 0
				String suf = oss[lb].substring(of);
				for(int j = 0;j < n;j++){
					if(oss[j].startsWith(suf) && !oss[j].equals(suf)){
						M[offset[j]+suf.length()-1][i+(2*U+1)*(suf.length()-1)] += 1;
					}
				}
			}
		}
		for(int i = 0;i < 2*U+1;i++){
			for(int j = 0;j < D-1;j++){
				M[i+(2*U+1)*(j+1)][i+(2*U+1)*j] = 1;
			}
		}

//		for(int[] row : M){
//			tr(row);
//		}

		int[] v = new int[(2*U+1)*D];
		v[0] = 1;
		v = pow(M, v, m);
//		for(int i = 1;i < U+1;i++){
//			if(v[i] != v[i+U]){
//				tr("diff", i, i+U, v[i], v[i+U]);
//			}
//		}
//		tr(v);
		out.println(v[0]);
	}

	///////// begin
	public static final int mod = 998244353;
	public static final long m2 = (long)mod*mod;
	public static final long BIG = 8L*m2;

	// A^e*v
	public static int[] pow(int[][] A, int[] v, long e)
	{
		for(int i = 0;i < v.length;i++){
			if(v[i] >= mod)v[i] %= mod;
		}
		int[][] MUL = A;
		for(;e > 0;e>>>=1) {
			if((e&1)==1)v = mul(MUL, v);
			MUL = p2(MUL);
		}
		return v;
	}

	// int matrix*int vector
	public static int[] mul(int[][] A, int[] v)
	{
		int m = A.length;
		int n = v.length;
		int[] w = new int[m];
		for(int i = 0;i < m;i++){
			long sum = 0;
			for(int k = 0;k < n;k++){
				sum += (long)A[i][k] * v[k];
				if(sum >= BIG)sum -= BIG;
			}
			w[i] = (int)(sum % mod);
		}
		return w;
	}

	// int matrix^2 (be careful about negative value)
	public static int[][] p2(int[][] A)
	{
		int n = A.length;
		int[][] C = new int[n][n];
		for(int i = 0;i < n;i++){
			long[] sum = new long[n];
			for(int k = 0;k < n;k++){
				for(int j = 0;j < n;j++){
					sum[j] += (long)A[i][k] * A[k][j];
					if(sum[j] >= BIG)sum[j] -= BIG;
				}
			}
			for(int j = 0;j < n;j++){
				C[i][j] = (int)(sum[j] % mod);
			}
		}
		return C;
	}

	public static int lowerBound(int[] a, int v){ return lowerBound(a, 0, a.length, v); }
	public static int lowerBound(int[] a, int l, int r, int v)
	{
		if(l > r || l < 0 || r > a.length)throw new IllegalArgumentException();
		int low = l-1, high = r;
		while(high-low > 1){
			int h = high+low>>>1;
			if(a[h] >= v){
				high = h;
			}else{
				low = h;
			}
		}
		return high;
	}

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

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

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

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

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

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

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

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

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

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

	private long[] nal(int n)
	{
		long[] a = new long[n];
		for(int i = 0;i < n;i++)a[i] = nl();
		return a;
	}

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

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

	private int ni() { return (int)nl(); }

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

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

	public static class FastWriter
	{
		private static final int BUF_SIZE = 1<<13;
		private final byte[] buf = new byte[BUF_SIZE];
		private final OutputStream out;
		private int ptr = 0;

		private FastWriter(){out = null;}

		public FastWriter(OutputStream os)
		{
			this.out = os;
		}

		public FastWriter(String path)
		{
			try {
				this.out = new FileOutputStream(path);
			} catch (FileNotFoundException e) {
				throw new RuntimeException("FastWriter");
			}
		}

		public FastWriter write(byte b)
		{
			buf[ptr++] = b;
			if(ptr == BUF_SIZE)innerflush();
			return this;
		}

		public FastWriter write(char c)
		{
			return write((byte)c);
		}

		public FastWriter write(char[] s)
		{
			for(char c : s){
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			}
			return this;
		}

		public FastWriter write(String s)
		{
			s.chars().forEach(c -> {
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			});
			return this;
		}

		private static int countDigits(int l) {
			if (l >= 1000000000) return 10;
			if (l >= 100000000) return 9;
			if (l >= 10000000) return 8;
			if (l >= 1000000) return 7;
			if (l >= 100000) return 6;
			if (l >= 10000) return 5;
			if (l >= 1000) return 4;
			if (l >= 100) return 3;
			if (l >= 10) return 2;
			return 1;
		}

		public FastWriter write(int x)
		{
			if(x == Integer.MIN_VALUE){
				return write((long)x);
			}
			if(ptr + 12 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		private static int countDigits(long l) {
			if (l >= 1000000000000000000L) return 19;
			if (l >= 100000000000000000L) return 18;
			if (l >= 10000000000000000L) return 17;
			if (l >= 1000000000000000L) return 16;
			if (l >= 100000000000000L) return 15;
			if (l >= 10000000000000L) return 14;
			if (l >= 1000000000000L) return 13;
			if (l >= 100000000000L) return 12;
			if (l >= 10000000000L) return 11;
			if (l >= 1000000000L) return 10;
			if (l >= 100000000L) return 9;
			if (l >= 10000000L) return 8;
			if (l >= 1000000L) return 7;
			if (l >= 100000L) return 6;
			if (l >= 10000L) return 5;
			if (l >= 1000L) return 4;
			if (l >= 100L) return 3;
			if (l >= 10L) return 2;
			return 1;
		}

		public FastWriter write(long x)
		{
			if(x == Long.MIN_VALUE){
				return write("" + x);
			}
			if(ptr + 21 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		public FastWriter write(double x, int precision)
		{
			if(x < 0){
				write('-');
				x = -x;
			}
			x += Math.pow(10, -precision)/2;
			//		if(x < 0){ x = 0; }
			write((long)x).write(".");
			x -= (long)x;
			for(int i = 0;i < precision;i++){
				x *= 10;
				write((char)('0'+(int)x));
				x -= (int)x;
			}
			return this;
		}

		public FastWriter writeln(char c){
			return write(c).writeln();
		}

		public FastWriter writeln(int x){
			return write(x).writeln();
		}

		public FastWriter writeln(long x){
			return write(x).writeln();
		}

		public FastWriter writeln(double x, int precision){
			return write(x, precision).writeln();
		}

		public FastWriter write(int... xs)
		{
			boolean first = true;
			for(int x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter write(long... xs)
		{
			boolean first = true;
			for(long x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter writeln()
		{
			return write((byte)'\n');
		}

		public FastWriter writeln(int... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(long... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(char[] line)
		{
			return write(line).writeln();
		}

		public FastWriter writeln(char[]... map)
		{
			for(char[] line : map)write(line).writeln();
			return this;
		}

		public FastWriter writeln(String s)
		{
			return write(s).writeln();
		}

		private void innerflush()
		{
			try {
				out.write(buf, 0, ptr);
				ptr = 0;
			} catch (IOException e) {
				throw new RuntimeException("innerflush");
			}
		}

		public void flush()
		{
			innerflush();
			try {
				out.flush();
			} catch (IOException e) {
				throw new RuntimeException("flush");
			}
		}

		public FastWriter print(byte b) { return write(b); }
		public FastWriter print(char c) { return write(c); }
		public FastWriter print(char[] s) { return write(s); }
		public FastWriter print(String s) { return write(s); }
		public FastWriter print(int x) { return write(x); }
		public FastWriter print(long x) { return write(x); }
		public FastWriter print(double x, int precision) { return write(x, precision); }
		public FastWriter println(char c){ return writeln(c); }
		public FastWriter println(int x){ return writeln(x); }
		public FastWriter println(long x){ return writeln(x); }
		public FastWriter println(double x, int precision){ return writeln(x, precision); }
		public FastWriter print(int... xs) { return write(xs); }
		public FastWriter print(long... xs) { return write(xs); }
		public FastWriter println(int... xs) { return writeln(xs); }
		public FastWriter println(long... xs) { return writeln(xs); }
		public FastWriter println(char[] line) { return writeln(line); }
		public FastWriter println(char[]... map) { return writeln(map); }
		public FastWriter println(String s) { return writeln(s); }
		public FastWriter println() { return writeln(); }
	}

	public void trnz(int... o)
	{
		for(int i = 0;i < o.length;i++)if(o[i] != 0)System.out.print(i+":"+o[i]+" ");
		System.out.println();
	}

	// print ids which are 1
	public void trt(long... o)
	{
		Queue<Integer> stands = new ArrayDeque<>();
		for(int i = 0;i < o.length;i++){
			for(long x = o[i];x != 0;x &= x-1)stands.add(i<<6|Long.numberOfTrailingZeros(x));
		}
		System.out.println(stands);
	}

	public void tf(boolean... r)
	{
		for(boolean x : r)System.out.print(x?'#':'.');
		System.out.println();
	}

	public void tf(boolean[]... b)
	{
		for(boolean[] r : b) {
			for(boolean x : r)System.out.print(x?'#':'.');
			System.out.println();
		}
		System.out.println();
	}

	public void tf(long[]... b)
	{
		if(INPUT.length() != 0) {
			for (long[] r : b) {
				for (long x : r) {
					for (int i = 0; i < 64; i++) {
						System.out.print(x << ~i < 0 ? '#' : '.');
					}
				}
				System.out.println();
			}
			System.out.println();
		}
	}

	public void tf(long... b)
	{
		if(INPUT.length() != 0) {
			for (long x : b) {
				for (int i = 0; i < 64; i++) {
					System.out.print(x << ~i < 0 ? '#' : '.');
				}
			}
			System.out.println();
		}
	}

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