use std::io::{self, BufRead, Write};
use std::str::{self, FromStr};
use std::fmt::Debug;

const P: i32 = 998244353;

fn mul(x: i32, y: i32) -> i32 {
    ((x as i64) * (y as i64) % (P as i64)) as i32
}

fn add_mul(z: i32, x: i32, y: i32) -> i32 {
    ((z as i64 + (x as i64) * (y as i64)) % (P as i64)) as i32
}

#[allow(unused_variables)]
fn solve(input: &mut FastDynInput<'_>, output: &mut dyn Write) -> io::Result<()> {

    let n = input.iread();
    let x = input.iread();
    let mut res: Vec<Vec<i32>> = vec![vec![0; (x+1) as usize]; (n+1) as usize];
    let mut bin: Vec<Vec<i32>> = vec![vec![0;(n+1) as usize]; (n+1) as usize];
    for i in 0..=n {
        bin[0 as usize][i as usize] = 1;
    }
    for i in 1..=n {
        bin[i as usize][0 as usize] = 1;
        for j in 1..=n {
            bin[i as usize][j as usize] = (bin[(i - 1) as usize][j as usize] + bin[i as usize][(j - 1) as usize]) % P;
        }
    }
    for i in 2..=n {
        for j in 1..=x {
            let mut cur = 1i32;
            if i - 1 >= j {
                for _ in 0..i {
                    cur = mul(cur, j);
                }
            } else {
                for _ in 0..i {
                    cur = mul(cur, i - 1);
                }
                let mut mult = 1i32;
                for left in (2..=i).into_iter().rev() {
                    let next = res[left as usize][(j - i + 1) as usize];
                    cur = add_mul(cur, next, mul(mult, bin[left as usize][(i - left) as usize]));
                    mult = mul(mult, i - 1);
                }
            }
            res[i as usize][j as usize] = cur;
        }
    }
    writeln!(output, "{}", res[n as usize][x as usize])?;
    Ok(())
}

#[test]
fn test1() {
    test_solve("2 5", "5");
    test_solve("3 3", "15");
    test_solve("5 4", "1024");
    test_solve("13 37", "976890680");
}

fn test_solve(input: &str, output: &str) {
    let mut writer = Vec::new();
    solve(&mut FastDynInput::from(input.as_bytes()), &mut writer).unwrap();
    assert_eq!(bytes_to_str(&writer).split_ascii_whitespace().collect::<Vec<_>>(),
               output.split_ascii_whitespace().collect::<Vec<_>>());
}

fn bytes_to_str(vec: &[u8]) -> &str {
    str::from_utf8(vec).unwrap()
}

struct FastDynInput<'a> {
    stdin: Box<dyn BufRead + 'a>,
}

impl<'a, R: BufRead + 'a> From<R> for FastDynInput<'a> {
    fn from(r: R) -> Self {
        Self {
            stdin: Box::new(r),
        }
    }
}

#[allow(dead_code)]
impl FastDynInput<'_> {
    fn read_bytes(&mut self) -> Vec<u8> {
        let mut bytes: Vec<u8> = Vec::new();
        let mut skip_space = true;
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                if buf.is_empty() {
                    break;
                }
                let mut pos: usize = 0;
                if skip_space {
                    while pos < buf.len() && buf[pos] <= 32 {
                        pos += 1;
                    }
                    if pos < buf.len() {
                        skip_space = false;
                    } else {
                        self.stdin.consume(pos);
                        continue;
                    }
                }
                while pos < buf.len() && buf[pos] > 32 {
                    bytes.push(buf[pos]);
                    pos += 1;
                }
                if pos < buf.len() {
                    self.stdin.consume(pos);
                    break;
                }
                self.stdin.consume(pos);
            } else {
                break;
            }
        }
        bytes
    }

    fn read_word(&mut self) -> String {
        String::from_utf8(self.read_bytes()).unwrap()
    }

    fn try_read_word(&mut self) -> Option<String> {
        let result = self.read_bytes();
        if result.is_empty() {
            return None;
        }
        String::from_utf8(result).ok()
    }

    fn read_line_bytes(&mut self) -> Option<Vec<u8>> {
        let mut bytes: Vec<u8> = Vec::new();
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                if buf.is_empty() {
                    if bytes.is_empty() {
                        return None;
                    }
                    break;
                }
                let mut pos: usize = 0;
                while pos < buf.len() && buf[pos] != b'\n' {
                    if buf[pos] != b'\r' {
                        bytes.push(buf[pos]);
                    }
                    pos += 1;
                }
                if pos < buf.len() {
                    pos += 1;
                    self.stdin.consume(pos);
                    break;
                }
                self.stdin.consume(pos);
            } else {
                break;
            }
        }
        Some(bytes)
    }

    fn read_line(&mut self) -> String {
        String::from_utf8(self.read_line_bytes().unwrap()).unwrap()
    }

    fn try_read_line(&mut self) -> Option<String> {
        String::from_utf8(self.read_line_bytes()?).ok()
    }

    fn iread(&mut self) -> i32 {
        self.read()
    }

    fn uread(&mut self) -> u32 {
        self.read()
    }

    fn dread(&mut self) -> f64 {
        self.read()
    }

    fn lread(&mut self) -> i64 {
        self.read()
    }

    fn read<V>(&mut self) -> V
        where V: FromStr,
              V::Err: Debug {
        self.read_word().parse::<V>().unwrap()
    }

    fn parse<V: FromStr>(&mut self) -> Result<V, V::Err> {
        self.read_word().parse::<V>()
    }
}

fn main() -> io::Result<()> {
    let stdin = io::stdin();
    let mut input = FastDynInput::from(stdin.lock());
    let stdout = io::stdout();
    let stdout_lock = stdout.lock();
    let mut output = io::BufWriter::with_capacity(1 << 16, stdout_lock);
    solve(&mut input, &mut output)
}


use std::*;

fn read_line() -> String {
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    line
}

fn read_vec<T: str::FromStr>() -> Vec<T> {
    read_line()
        .split_whitespace()
        .filter_map(|i| i.parse().ok())
        .collect()
}

fn main() {
    const M: i64 = 998244353;
    if let [n, m] = read_vec::<usize>()[..] {
        let mut choose = vec![vec![0; n + 1]; n + 1];
        for i in 0..=n {
            choose[i][0] = 1;
            for j in 1..=i {
                choose[i][j] = choose[i - 1][j - 1] + choose[i - 1][j];
                if choose[i][j] >= M {
                    choose[i][j] -= M;
                }
            }
        }

        let mut dp = vec![vec![0; m + 1]; n + 1];
        dp[1][1..].fill(1);
        for i in 1..n {
            let pow = iter::successors(Some(1), |&x| Some(x * i as i64 % M))
                .take(i + 1)
                .collect::<Vec<_>>();
            for j in 1..=m {
                let mut s = 0;
                for k in (i..j).step_by(i) {
                    let jj = j - k;
                    for ii in 1..=i {
                        s += dp[ii][jj] * choose[i + 1][ii] % M * pow[i + 1 - ii] % M;
                    }
                }
                dp[i + 1][j] = s % M;
            }
        }

        let mut ans = 1;
        for _ in 0..n {
            ans = ans * m as i64 % M;
        }
        ans -= dp[n].iter().sum::<i64>();
        println!("{}", ans.rem_euclid(M));
    }
}


/*
    date   : 2021 / 4 / 7
    author : quickn (quickn.tech)
    email  : quickwshell@gmail.com
*/

use std::io::{self, BufWriter, Write};

mod scanner {
    use std::{io, str};
    /* https://github.com/EbTech/rust-algorithms */

    /// Same API as Scanner but nearly twice as fast, using horribly unsafe dark arts
    /// **REQUIRES** Rust 1.34 or higher
    pub struct UnsafeScanner<R> {
        reader: R,
        buf_str: Vec<u8>,
        buf_iter: str::SplitAsciiWhitespace<'static>,
    }

    impl<R: io::BufRead> UnsafeScanner<R> {
        pub fn new(reader: R) -> Self {
            Self {
                reader,
                buf_str: Vec::new(),
                buf_iter: "".split_ascii_whitespace(),
            }
        }

        /// This function should be marked unsafe, but noone has time for that in a
        /// programming contest. Use at your own risk!
        pub fn token<T: str::FromStr>(&mut self) -> T {
            loop {
                if let Some(token) = self.buf_iter.next() {
                    return token.parse().ok().expect("Failed parse");
                }
                self.buf_str.clear();
                self.reader
                    .read_until(b'\n', &mut self.buf_str)
                    .expect("Failed read");
                self.buf_iter = unsafe {
                    let slice = str::from_utf8_unchecked(&self.buf_str);
                    std::mem::transmute(slice.split_ascii_whitespace())
                }
            }
        }
    }
}

use std::cmp::{min, max};

fn s2vec(s: String) -> Vec<char> {
    s.chars().collect()
}

const MOD: i64 = 998244353;

const MAX: usize = 501;

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let (mut scan, mut sout) = (
        scanner::UnsafeScanner::new(stdin.lock()),
        BufWriter::new(stdout.lock()),
    );
    let n: usize = scan.token();
    let x: usize = scan.token();
    let mut dp: Vec<Vec<i64>> = vec![vec![0;MAX];n+1];
    let mut binom: Vec<Vec<i64>> = vec![vec![0;MAX+1];MAX+1];
    let mut pow_mod: Vec<Vec<i64>> = vec![vec![0;MAX+1];MAX+1];
    for a in 1..MAX {
        let mut val = 1;
        for x in 0..MAX {
            pow_mod[a][x] = val;
            val *= a as i64;
            val %= MOD;
        }
    }
    binom[0][0] = 1;
    for i in 1..=MAX {
        binom[i][0] = 1;
        binom[i][i] = 1;
        for j in 1..i {
            binom[i][j] += binom[i-1][j-1];
            binom[i][j] %= MOD;
            binom[i][j] += binom[i-1][j];
            binom[i][j] %= MOD;
        }
    }
    dp[n][0] = 1;
    for r in (1..=n).rev() {
        for lx in 0..=x {
            for y in 0..=(n-r) {
                if lx >= y+r-1 {
                    let d = max(0, min(x-lx+(y+r-1), y+r-1));
                    dp[r][lx] += (((dp[r+y][lx-(y+r-1)]*binom[y+r][y])%MOD)*pow_mod[d][y])%MOD;
                    dp[r][lx] %= MOD;
                }
            }
        }
    }
    let mut all = pow_mod[x][n];
    for lx in 0..=x {
        all -= (dp[1][lx]*((x - lx) as i64))%MOD;
        all += MOD;
        all %= MOD;
    }
    writeln!(sout, "{}", all).ok();
}


use std::convert::TryInto as _;
use std::io::{Result, Write as _};

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

const MOD: i64 = 998_244_353;

const fn pow(b: i64, mut x: i64) -> i64 {
    let mut m = b;
    let mut ret = 1;
    while x > 0 {
        if (x & 1) > 0 {
            ret = ret * m % MOD;
        }
        m = m * m % MOD;
        x >>= 1;
    }

    ret
}

const fn inverse(n: i64) -> i64 {
    pow(n, MOD - 2)
}

const fn make_factorials() -> ([i64; 501], [i64; 501]) {
    let mut fact = [0; 501];
    let mut inv = [0; 501];

    fact[0] = 1;
    inv[0] = 1;

    let mut i = 1;
    while i <= 500 {
        let j = i as i64;
        fact[i] = fact[i - 1] * j % MOD;
        i += 1;
    }

    inv[500] = inverse(fact[500]);

    let mut i = 499;
    while i > 0 {
        let j = i as i64;
        inv[i] = inv[i + 1] * (j + 1) % MOD;
        i -= 1;
    }

    (fact, inv)
}

fn make_powers() -> [[i64; 501]; 501] {
    let mut powers = [[0; 501]; 501];

    for b in 1..=500 {
        let bi64 = b.try_into().unwrap();
        powers[b][1] = bi64;
        for x in 2..=500 {
            powers[b][x] = powers[b][x - 1] * bi64 % MOD;
        }
    }

    powers
}

const FACTORIALS: ([i64; 501], [i64; 501]) = make_factorials();

fn main() -> Result<()> {
    let mut scanner = Scanner::default();
    let out = &mut std::io::BufWriter::new(std::io::stdout());

    let (fact, inv) = FACTORIALS;
    let powers = make_powers();

    let c = |n, k| fact[n] * inv[k] % MOD * inv[n - k] % MOD;

    let n: usize = scanner.next();
    let x = scanner.next();

    let mut dp = vec![vec![0; x + 1]; n + 1];
    for i in 1..=x {
        dp[1][i] = n.try_into().unwrap();
    }

    for i in 1..n {
        for j in 1..x {
            for k in (i + 1)..=n {
                // dp[i][j] -> dp[k][?]
                let max = (x - j) / (k - 1);
                for l in 1..=max {
                    let nj = j + l * (k - 1);
                    debug_assert!(nj <= x);
                    dp[k][nj] = (dp[k][nj] + dp[i][j] * c(n - i, k - i) % MOD * powers[k - 1][k - i] % MOD) % MOD;
                }
            }
        }
    }

    let sum = dp[n].iter().fold(0, |acc, x| (acc + x) % MOD);
    let ret = (pow(x.try_into().unwrap(), n.try_into().unwrap()) + MOD - sum) % MOD;

    writeln!(out, "{}", ret)?;

    Ok(())
}


use std::{io, io::prelude::*, str};

struct Scanner<R> {
    reader: R,
    buffer: Vec<String>,
}
impl<R: io::BufRead> Scanner<R> {
    fn new(reader: R) -> Self {
        Self {
            reader,
            buffer: vec![],
        }
    }

    fn t<T: str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            self.reader.read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

use std::ops;

#[derive(Copy, Clone)]
struct ModGroup {
    val: usize,
}
impl ModGroup {
    const MOD: usize = 998244353;
    const MOD64: i64 = Self::MOD as i64;

    fn new(v: usize) -> Self {
        Self { val: v }
    }

    fn from_usize(v: usize) -> Self {
        Self { val: v % Self::MOD }
    }

    fn from_i64(v: i64) -> Self {
        Self {
            val: (v % Self::MOD64) as usize,
        }
    }

    fn pow(self, mut p: usize) -> Self {
        let mut base = self;
        let mut res = Self::new(1);
        while p > 0 {
            if p % 2 > 0 {
                res = res * base;
            }
            base = base * base;
            p /= 2;
        }

        res
    }

    fn inv(self) -> Self {
        self.pow(Self::MOD - 2)
    }
}

impl ops::Add<usize> for ModGroup {
    type Output = Self;

    fn add(self, other: usize) -> Self {
        Self::from_usize(self.val + other)
    }
}
impl ops::Add<ModGroup> for ModGroup {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        self + other.val
    }
}
impl ops::Sub<usize> for ModGroup {
    type Output = Self;

    fn sub(self, other: usize) -> Self {
        Self::new(if self.val >= other {
            self.val - other
        } else {
            self.val + Self::MOD - other
        })
    }
}
impl ops::Sub<ModGroup> for ModGroup {
    type Output = Self;

    fn sub(self, other: Self) -> Self {
        self - other.val
    }
}
impl ops::Mul<usize> for ModGroup {
    type Output = Self;

    fn mul(self, other: usize) -> Self {
        Self::from_i64(self.val as i64 * other as i64)
    }
}
impl ops::Mul<ModGroup> for ModGroup {
    type Output = Self;

    fn mul(self, other: Self) -> Self {
        self * other.val
    }
}
impl ops::Div<usize> for ModGroup {
    type Output = Self;

    fn div(self, other: usize) -> Self {
        self * Self::new(other).inv()
    }
}
impl ops::Div<ModGroup> for ModGroup {
    type Output = Self;

    fn div(self, other: Self) -> Self {
        self * other.inv()
    }
}

fn main() -> io::Result<()> {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout);

    const N: usize = 501;

    let fact = {
        let mut fact = vec![ModGroup::from_usize(1); N];
        for i in 1..N {
            fact[i] = fact[i - 1] * i;
        }
        fact
    };
    let bin_coef = {
        let mut bin_coef = vec![vec![ModGroup::from_usize(0); N]; N];
        for i in 1..N {
            for j in 1..=i {
                bin_coef[i][j] = fact[i] / (fact[j] * fact[i - j]);
            }
        }
        bin_coef
    };
    let pow_n = {
        let mut pow_n = vec![vec![ModGroup::from_usize(1); N]; N];
        for i in 1..N {
            for j in 1..N {
                pow_n[i][j] = pow_n[i][j - 1] * i;
            }
        }
        pow_n
    };

    let (n, m): (usize, usize) = (scan.t(), scan.t());
    let mut dp = vec![vec![ModGroup::from_usize(0); m + 1]; m + 1];
    for h in 1..=m {
        dp[h][h] = pow_n[h - 1][h - 1] * h;
        for d in 2..h {
            let mut cur = dp[d][d];
            let h1 = h - d + 1;
            for k in 2..=d {
                cur = cur + dp[h1][k] * bin_coef[d][k] * pow_n[d - 1][d - k];
            }

            dp[h][d] = cur;
        }
    }

    let mut res = ModGroup::from_usize(0);
    if m >= n {
        for i in 1..=m {
            res = res + dp[i][n];
        }
    }
    res = pow_n[m][n] - res;
    writeln!(out, "{}", res.val)?;

    io::Result::Ok(())
}


use crate::mod_int::ModInt;

fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());
    let n: usize = sc.read();
    let x: usize = sc.read();

    let comb = Combination::new(n.max(x) * 2 + 1, 998244353);
    let mut dp = vec![vec![ModInt::from(0); x + 1]; n + 1];

    for last in 2..=n {
        for max_hp in 1..=x {
            if max_hp > last - 1 {
                break;
            }
            let c = ModInt::from(comb.get(n, last));
            let d = distribution(max_hp, last);
            dp[last][max_hp] = c * d;
        }
    }

    for cur_alive in 2..=n {
        for cur_max_hp in 1..=x {
            for next_alive in cur_alive..=n {
                let cur_dp = dp[cur_alive][cur_max_hp];
                let new_people = next_alive - cur_alive;
                let damage = next_alive - 1;
                if cur_max_hp + damage > x {
                    break;
                }

                let c = comb.get(n - cur_alive, new_people);
                let d = ModInt::from(damage).pow(new_people);
                dp[next_alive][cur_max_hp + damage] += cur_dp * c * d;
            }
        }
    }

    let mut ans = ModInt::from(0);
    for x in 0..=x {
        ans += dp[n][x];
    }
    println!("{}", ans.value());

    // for i in 1..=n {
    //     for j in 1..=x {
    //         print!("{} ", dp[i][j].value());
    //     }
    //     println!();
    // }
}

fn distribution(max_hp: usize, people: usize) -> ModInt {
    ModInt::from(max_hp).pow(people) - ModInt::from(max_hp - 1).pow(people)
}

pub struct Combination {
    fact: Vec<usize>,
    inv_fact: Vec<usize>,
    modulo: usize,
}

impl Combination {
    pub fn new(max: usize, modulo: usize) -> Self {
        let mut inv = vec![0; max + 1];
        let mut fact = vec![0; max + 1];
        let mut inv_fact = vec![0; max + 1];
        inv[1] = 1;
        for i in 2..(max + 1) {
            inv[i] = inv[modulo % i] * (modulo - modulo / i) % modulo;
        }
        fact[0] = 1;
        inv_fact[0] = 1;
        for i in 0..max {
            fact[i + 1] = fact[i] * (i + 1) % modulo;
        }
        for i in 0..max {
            inv_fact[i + 1] = inv_fact[i] * inv[i + 1] % modulo;
        }
        Self {
            fact,
            inv_fact,
            modulo,
        }
    }

    pub fn get(&self, x: usize, y: usize) -> usize {
        assert!(x >= y);
        self.fact[x] * self.inv_fact[y] % self.modulo * self.inv_fact[x - y] % self.modulo
    }

    pub fn h(&self, n: usize, r: usize) -> usize {
        self.get(n + r - 1, r)
    }
}
pub mod mod_int {
    type ModInternalNum = i64;
    thread_local!(
        static MOD: std::cell::RefCell<ModInternalNum> = std::cell::RefCell::new(0);
    );

    pub fn set_mod_int<T: ToInternalNum>(v: T) {
        MOD.with(|x| x.replace(v.to_internal_num()));
    }
    fn modulo() -> ModInternalNum {
        998244353
    }

    #[derive(Debug)]
    pub struct ModInt(ModInternalNum);
    impl Clone for ModInt {
        fn clone(&self) -> Self {
            Self(self.0)
        }
    }
    impl Copy for ModInt {}

    impl ModInt {
        fn internal_new(mut v: ModInternalNum) -> Self {
            let m = modulo();
            if v >= m {
                v %= m;
            }
            Self(v)
        }

        pub fn internal_pow(&self, mut e: ModInternalNum) -> Self {
            let mut result = 1;
            let mut cur = self.0;
            let modulo = modulo();
            while e > 0 {
                if e & 1 == 1 {
                    result *= cur;
                    result %= modulo;
                }
                e >>= 1;
                cur = (cur * cur) % modulo;
            }
            Self(result)
        }

        pub fn pow<T>(&self, e: T) -> Self
        where
            T: ToInternalNum,
        {
            self.internal_pow(e.to_internal_num())
        }

        pub fn value(&self) -> ModInternalNum {
            self.0
        }
    }

    pub trait ToInternalNum {
        fn to_internal_num(&self) -> ModInternalNum;
    }
    impl ToInternalNum for ModInt {
        fn to_internal_num(&self) -> ModInternalNum {
            self.0
        }
    }
    macro_rules! impl_primitive {
        ($primitive:ident) => {
            impl From<$primitive> for ModInt {
                fn from(v: $primitive) -> Self {
                    let v = v as ModInternalNum;
                    Self::internal_new(v)
                }
            }
            impl ToInternalNum for $primitive {
                fn to_internal_num(&self) -> ModInternalNum {
                    *self as ModInternalNum
                }
            }
        };
    }
    impl_primitive!(u8);
    impl_primitive!(u16);
    impl_primitive!(u32);
    impl_primitive!(u64);
    impl_primitive!(usize);
    impl_primitive!(i8);
    impl_primitive!(i16);
    impl_primitive!(i32);
    impl_primitive!(i64);
    impl_primitive!(isize);

    impl<T: ToInternalNum> std::ops::AddAssign<T> for ModInt {
        fn add_assign(&mut self, rhs: T) {
            let mut rhs = rhs.to_internal_num();
            let m = modulo();
            if rhs >= m {
                rhs %= m;
            }

            self.0 += rhs;
            if self.0 >= m {
                self.0 -= m;
            }
        }
    }

    impl<T: ToInternalNum> std::ops::Add<T> for ModInt {
        type Output = ModInt;
        fn add(self, rhs: T) -> Self::Output {
            let mut res = self;
            res += rhs;
            res
        }
    }
    impl<T: ToInternalNum> std::ops::SubAssign<T> for ModInt {
        fn sub_assign(&mut self, rhs: T) {
            let mut rhs = rhs.to_internal_num();
            let m = modulo();
            if rhs >= m {
                rhs %= m;
            }
            if rhs > 0 {
                self.0 += m - rhs;
            }
            if self.0 >= m {
                self.0 -= m;
            }
        }
    }
    impl<T: ToInternalNum> std::ops::Sub<T> for ModInt {
        type Output = Self;
        fn sub(self, rhs: T) -> Self::Output {
            let mut res = self;
            res -= rhs;
            res
        }
    }
    impl<T: ToInternalNum> std::ops::MulAssign<T> for ModInt {
        fn mul_assign(&mut self, rhs: T) {
            let mut rhs = rhs.to_internal_num();
            let m = modulo();
            if rhs >= m {
                rhs %= m;
            }
            self.0 *= rhs;
            self.0 %= m;
        }
    }
    impl<T: ToInternalNum> std::ops::Mul<T> for ModInt {
        type Output = Self;
        fn mul(self, rhs: T) -> Self::Output {
            let mut res = self;
            res *= rhs;
            res
        }
    }

    impl<T: ToInternalNum> std::ops::DivAssign<T> for ModInt {
        fn div_assign(&mut self, rhs: T) {
            let mut rhs = rhs.to_internal_num();
            let m = modulo();
            if rhs >= m {
                rhs %= m;
            }
            let inv = Self(rhs).internal_pow(m - 2);
            self.0 *= inv.value();
            self.0 %= m;
        }
    }

    impl<T: ToInternalNum> std::ops::Div<T> for ModInt {
        type Output = Self;
        fn div(self, rhs: T) -> Self::Output {
            let mut res = self;
            res /= rhs;
            res
        }
    }
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> IO<R, W> {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: ToString>(&mut self, s: S) {
        use std::io::Write;
        self.1.write_all(s.to_string().as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn usize0(&mut self) -> usize {
        self.read::<usize>() - 1
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


#![allow(unused_imports)]
#![allow(dead_code)]
#![allow(unused_variables)]
use std::cmp::min;
use std::io;
use std::{io::prelude::*, io::*, str};

struct IO {
    buffer: Vec<String>,
    out: BufWriter<Stdout>,
}
impl IO {
    fn new() -> Self {
        Self {
            buffer: vec![],
            out: BufWriter::new(stdout()),
        }
    }
    fn read<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
    fn read_vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read::<T>()).collect()
    }
}

const MOD: u64 = 998244353;

fn fastpow(mut a: u64, mut x: u64) -> u64 {
    let mut r = 1;
    while x != 0 {
        if x & 1 != 0 {
            r = (r * a) % MOD;
        }

        a = (a * a) % MOD;
        x >>= 1;
    }
    r
}

fn modinv(x: u64) -> u64 {
    fastpow(x, MOD - 2)
}

fn solve(io: &mut IO) -> Result<()> {
    let (n, x): (usize, usize) = (io.read(), io.read());
    let mut comb = vec![vec![1; n + 1]; n + 1];
    let mut comb2 = vec![vec![1; n + 1]; n + 1];
    let mut fact = vec![1; n + 1];

    for i in 1..=n {
        fact[i] = (fact[i - 1] * (i as u64)) % MOD;

        for j in 1..=i {
            let rem = (fact[j] * fact[i - j]) % MOD;
            let rinv = modinv(rem);

            comb[i][j] = (fact[i] * rinv) % MOD;

            comb2[i][j] = fastpow(i as u64 - 1, j as u64) * comb[i][j] % MOD;
        }
    }

    let mut dp = vec![vec![0; x + 1]; n + 1];
    dp[0] = vec![1; x + 1];

    for k in 2..=n {
        let mut sum = 0u64;
        for y in 1..=min(k - 1, x) {
            dp[k][y] = (fastpow(y as u64, k as u64) + MOD - sum) % MOD;
            sum = (sum + dp[k][y]) % MOD
        }

        for y in k..=x {
            let mut val = dp[k][y - (k - 1)];

            for i in 1..k {
                let a = dp[k - i][y - (k - 1)] * comb2[k][i] % MOD;
                val = (val + a) % MOD;
            }
            dp[k][y] = val;
        }
    }

    let mut cnt = 0;
    for y in 1..=x {
        cnt = (cnt + dp[n][y]) % MOD;
    }

    writeln!(io.out, "{}", cnt % MOD)
}

fn main() -> io::Result<()> {
    let mut io = IO::new();

    //for _ in 0..tc {
    solve(&mut io)
    //}
    //Ok(())
}


#![allow(dead_code, unused_macros, unused_imports)]
use std::{cell::{Cell, RefCell, UnsafeCell}, cmp::{Ordering, Reverse, max, min}, collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque, hash_map::{DefaultHasher, RandomState}}, error::Error, fmt::{Display, Write as FmtWrite}, hash::{BuildHasher, Hash, Hasher}, io::{BufWriter, Read, Stdin, Stdout, Write}, iter::{FromIterator, Peekable}, mem::swap, ops::*, process::exit, rc::Rc, str::{FromStr, from_utf8_unchecked}, time::{Duration, Instant}};

const IO_BUF_SIZE: usize = 1 << 16;
type Input = Scanner<Stdin>;
type Output = BufWriter<Stdout>;
fn _init_input() -> Input { Scanner::new(std::io::stdin()) }
fn _init_output() -> Output { BufWriter::with_capacity(IO_BUF_SIZE, std::io::stdout()) }

#[repr(transparent)] struct Unsync<T>(T);
unsafe impl<T> Sync for Unsync<T> {}

type BadLazy<T> = Unsync<UnsafeCell<Option<T>>>;
impl<T> BadLazy<T> {
    const fn new() -> Self { Self(UnsafeCell::new(None)) }
}

static INPUT: BadLazy<Input> = BadLazy::new();
static OUTPUT: BadLazy<Output> = BadLazy::new();

fn inp<F: FnOnce(&mut Input) -> R, R>(f: F) -> R {
    unsafe { f((&mut *INPUT.0.get()).get_or_insert_with(_init_input)) }
}
fn out<F: FnOnce(&mut Output) -> R, R>(f: F) -> R {
    unsafe { f((&mut *OUTPUT.0.get()).get_or_insert_with(_init_output)) }
}

macro_rules! read {
    () => { read() };
    ($t: ty) => { read::<$t>() };
    ($t: ty, $($tt: ty),*) => { (read::<$t>(), $(read::<$tt>(),)*) };
    [$t: ty; $n: expr] => { read_vec::<$t>($n) };
}
macro_rules! println {
    () => { out(|x| { let _ = writeln!(x); }) };
    ($exp: expr) => { out(|x| { let _ = writeln!(x, "{}", $exp); }) };
    ($fmt: expr, $($arg : tt )*) => { out(|x| { let _ = writeln!(x, $fmt, $($arg)*); }) }
}
macro_rules! print {
    ($exp: expr) => { out(|x| { let _ = write!(x, "{}", $exp); }) };
    ($fmt: expr, $($arg : tt )*) => { out(|x| { let _ = write!(x, $fmt, $($arg)*); }) }
}

fn out_flush() { out(|x| { let _ = x.flush(); }); }

fn input_is_eof() -> bool { inp(|x| x.eof()) }
fn read_byte() -> u8 { inp(|x| x.byte()) }
fn read_bytes_no_skip(n: usize) -> Vec<u8> { inp(|x| x.bytes_no_skip(n)) }
fn read_bytes(n: usize) -> Vec<u8> { inp(|x| x.bytes(n)) }
fn read_bytes2(n: usize, m: usize) -> Vec<Vec<u8>> { inp(|x| x.bytes2(n, m)) }
fn read_token() -> Vec<u8> { inp(|x| x.token_bytes()) }
fn read_token_str() -> String { unsafe { String::from_utf8_unchecked(read_token()) } }
fn read_line() -> Vec<u8> { inp(|x| x.line_bytes()) }
fn read_line_str() -> String { unsafe { String::from_utf8_unchecked(read_line()) } }
fn read<T: FromStr>() -> T { read_token_str().parse::<T>().ok().expect("failed parse") }
fn read_vec<T: FromStr>(n: usize) -> Vec<T> { (0..n).map(|_| read()).collect() }
fn read_vec2<T: FromStr>(n: usize, m: usize) -> Vec<Vec<T>> { (0..n).map(|_| read_vec(m)).collect() }

struct Scanner<R: Read> {
    src: R,
    _buf: Vec<u8>,
    _pt: usize, // pointer
    _rd: usize, // bytes read
}

#[allow(dead_code)]
impl<R: Read> Scanner<R> {
    fn new(src: R) -> Scanner<R> {
        Scanner { src, _buf: vec![0; IO_BUF_SIZE], _pt: 1, _rd: 1 }
    }

    fn _check_buf(&mut self) {
        if self._pt == self._rd {
            self._rd = self.src.read(&mut self._buf).unwrap_or(0);
            self._pt = (self._rd == 0) as usize;
        }
    }

    // returns true if end of file
    fn eof(&mut self) -> bool {
        self._check_buf();
        self._rd == 0
    }

    // filters \r, returns \0 if eof
    fn byte(&mut self) -> u8 {
        loop {
            self._check_buf();
            if self._rd == 0 { return 0; }
            let res = self._buf[self._pt];
            self._pt += 1;
            if res != b'\r' { return res; }
        }
    }

    fn bytes_no_skip(&mut self, n: usize) -> Vec<u8> { (0..n).map(|_| self.byte()).collect() }
    fn bytes(&mut self, n: usize) -> Vec<u8> {
        let res = self.bytes_no_skip(n);
        self.byte();
        res
    }
    fn bytes2(&mut self, n: usize, m: usize) -> Vec<Vec<u8>> { (0..n).map(|_| self.bytes(m)).collect() }

    fn token_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c <= b' ' {
            if c == b'\0' { return res; }
            c = self.byte();
        }
        loop {
            res.push(c);
            c = self.byte();
            if c <= b' ' { return res; }
        }
    }

    fn line_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c != b'\n' && c != b'\0' {
            res.push(c);
            c = self.byte();
        }
        res
    }
}

trait JoinToStr {
    fn join_to_str(self, sep: &str) -> String;
    fn concat_to_str(self) -> String;
}
impl<T: Display, I: Iterator<Item = T>> JoinToStr for I {
    fn join_to_str(mut self, sep: &str) -> String {
        match self.next() {
            Some(first) => {
                let mut res = first.to_string();
                while let Some(item) = self.next() {
                    res.push_str(sep);
                    res.push_str(&item.to_string());
                }
                res
            }
            None => { String::new() }
        }
    }

    fn concat_to_str(self) -> String {
        let mut res = String::new();
        for item in self { res.push_str(&item.to_string()); }
        res
    }
}
trait AsStr { fn as_str(&self) -> &str; }
impl AsStr for [u8] { fn as_str(&self) -> &str {std::str::from_utf8(self).expect("attempt to convert non-UTF8 byte string.")} }

macro_rules! veci {
    ($n:expr , $i:ident : $gen:expr) => {{
        let _veci_n = $n;
        let mut _veci_list = Vec::with_capacity(_veci_n);
        for $i in 0.._veci_n {
            _veci_list.push($gen);
        }
        _veci_list
    }};
    ($n:expr , $gen:expr) => { veci!($n, _veci_: $gen); }
}

fn abs_diff<T: Sub<Output = T> + PartialOrd>(x: T, y: T) -> T {
    if x < y { y - x } else { x - y }
}

trait CommonNumExt {
    fn div_ceil(self, b: Self) -> Self;
    fn div_floor(self, b: Self) -> Self;
    fn gcd(self, b: Self) -> Self;
    fn highest_one(self) -> Self;
    fn lowest_one(self) -> Self;
}

macro_rules! impl_common_num_ext {
    ($($ix:tt = $ux:tt),*) => {
        $(
            impl CommonNumExt for $ux {
                fn div_ceil(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if r != 0 { q + 1 } else { q }
                }
                fn div_floor(self, b: Self) -> Self { self / b }
                fn gcd(self, mut b: Self) -> Self {
                    let mut a = self; while a != 0 { swap(&mut a, &mut b); a %= b; }
                    b
                }
                #[inline] fn highest_one(self) -> Self {
                    if self == 0 { 0 } else { const ONE: $ux = 1; ONE.rotate_right(1) >> self.leading_zeros() }
                }
                #[inline] fn lowest_one(self) -> Self { self & self.wrapping_neg() }
            }

            impl CommonNumExt for $ix {
                fn div_ceil(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if self ^ b >= 0 && r != 0 { q + 1 } else { q }
                }
                fn div_floor(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if self ^ b < 0 && r != 0 { q - 1 } else { q }
                }
                fn gcd(self, mut b: Self) -> Self {
                    let mut a = self; while a != 0 { swap(&mut a, &mut b); a %= b; }
                    b.abs()
                }
                #[inline] fn highest_one(self) -> Self { (self as $ux).highest_one() as _ }
                #[inline] fn lowest_one(self) -> Self { self & self.wrapping_neg() }
            }
        )*
    }
}
impl_common_num_ext!(i8 = u8, i16 = u16, i32 = u32, i64 = u64, i128 = u128, isize = usize);

trait ChMaxMin<T> {
    fn set_max(&mut self, v: T) -> bool;
    fn set_min(&mut self, v: T) -> bool;
}
impl<T: PartialOrd> ChMaxMin<T> for T {
    fn set_max(&mut self, v: T) -> bool { if v > *self { *self = v; true } else { false } }
    fn set_min(&mut self, v: T) -> bool { if v < *self { *self = v; true } else { false } }
}

// * end commons * //

#[macro_use]
#[allow(dead_code)]
mod modint {
    use std::{fmt::{Display, Formatter}, marker::PhantomData, mem::swap, ops::*, str::FromStr, cell::Cell};
    use crate::ModInt;

    pub trait RemEuclidU32: Copy {
        /// Calculates `self` _mod_ `modulus` losslessly.
        fn rem_euclid_u32(self, modulus: u32) -> u32;
    }

    macro_rules! impl_rem_euclid_u32_for_small_signed {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self as i64).rem_euclid(i64::from(modulus)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_signed!(i8, i16, i32, i64, isize);

    impl RemEuclidU32 for i128 {
        #[inline]
        fn rem_euclid_u32(self, modulus: u32) -> u32 {
            self.rem_euclid(i128::from(modulus)) as _
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        self as u32 % modulus
                    }
                }
            )*
        }
    }

    macro_rules! impl_rem_euclid_u32_for_large_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self % (modulus as $ty)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_unsigned!(u8, u16, u32);
    impl_rem_euclid_u32_for_large_unsigned!(u64, u128);

    #[cfg(target_pointer_width = "32")]
    impl_rem_euclid_u32_for_small_unsigned!(usize);

    #[cfg(target_pointer_width = "64")]
    impl_rem_euclid_u32_for_large_unsigned!(usize);
    #[inline]
    pub fn mul_mod_u32(a: u32, b: u32, m: u32) -> u32 {
        (a as u64 * b as u64 % m as u64) as u32
    }

    // for a, b < m, unspecified otherwise
    #[inline]
    fn add_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.wrapping_sub(m).overflowing_add(b);
        if c { r } else { r.wrapping_add(m) }
    }
    #[inline]
    fn sub_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.overflowing_sub(b);
        if c { r.wrapping_add(m) } else { r }
    }
    fn pow_mod_raw(a: u32, mut k: u64, m: u32) -> u32 {
        if m == 1 { return 0; }
        let mut a = a as u64;
        let m = m as u64;
        let mut r: u64 = 1;
        while k > 0 {
            if k & 1 == 1 {
                r = r * a % m;
            }
            k >>= 1;
            a = a * a % m;
        }
        r as u32
    }

    /// # Parameters
    /// * `b` `1 <= b`
    /// # Returns
    /// (x, g) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = a.rem_euclid(b);
        if a == 0 { return (0, b); }
        let mut s = b;
        let mut t = a;
        let mut m0 = 0;
        let mut m1 = 1;

        while t != 0 {
            let u = s / t;
            s -= t * u;
            m0 -= m1 * u;
            swap(&mut s, &mut t);
            swap(&mut m0, &mut m1);
        }

        if m0 < 0 { m0 += b / s; }
        (m0, s)
    }

    pub trait Modulus: Copy + Eq {
        fn get_modulus() -> u32;
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash)]
    #[repr(transparent)]
    pub struct ModIntBase<M: Modulus> {
        val: u32,
        _phantom: PhantomData<M>
    }

    impl <M: Modulus> ModIntBase<M> {
        #[inline(always)]
        pub fn modulus() -> u32 { M::get_modulus() }
        #[inline] pub fn new<I: RemEuclidU32>(val: I) -> Self { Self::raw(val.rem_euclid_u32(Self::modulus())) }
        #[inline] pub fn raw(val: u32) -> Self { Self { val, _phantom: PhantomData } }
        pub fn inv(self) -> Self {
            let (x, gcd) = inv_gcd(self.val.into(), Self::modulus().into());
            debug_assert!(gcd == 1, "the multiplicative inverse {}^-1 mod {} does not exist", self.val, Self::modulus());
            Self::raw(x as u32)
        }
        #[inline] pub fn val(self) -> u32 { self.val }
        #[inline] pub fn pow(self, k: u64) -> Self {
            Self::raw(pow_mod_raw(self.val, k, Self::modulus()))
        }
        pub fn powi(self, k: i64) -> Self { if k < 0 { self.inv().pow(-k as _) } else { self.pow(k as _) } }
        pub fn pow_vec(self, n: usize) -> Vec<Self> {
            let mut res = vec![Self::raw(0); n+1];
            res[0] += 1;
            for i in 1..=n {
                res[i] = res[i-1] * self;
            }
            res
        }
    }

    #[inline]
    pub fn mi<I: RemEuclidU32>(val: I) -> ModInt { ModIntBase::new(val) }
    #[inline] pub fn mir(v: u32) -> ModInt { ModIntBase::raw(v) }

    impl<V: RemEuclidU32, M: Modulus> From<V> for ModIntBase<M> {
        #[inline]
        fn from(from: V) -> Self { Self::new(from) }
    }
    impl<M: Modulus> Default for ModIntBase<M> {
        fn default() -> Self { Self::raw(0) }
    }
    impl<M: Modulus> FromStr for ModIntBase<M> {
        type Err = std::convert::Infallible;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(s.parse::<i64>()
            .map(Self::new)
            .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }
    }
    impl<M: Modulus> Display for ModIntBase<M> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
            self.val.fmt(f)
        }
    }
    impl<M: Modulus> std::fmt::Debug for ModIntBase<M> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.val, f)
        }
    }
    impl<M: Modulus> Neg for ModIntBase<M> {
        type Output = Self;

        #[inline]
        fn neg(self) -> Self::Output {
            Self::raw(0) - self
        }
    }

    impl<V: Into<ModIntBase<M>>, M: Modulus> Add<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn add(self, rhs: V) -> Self::Output {
            Self::raw(add_mod_raw(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Sub<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn sub(self, rhs: V) -> Self::Output {
            Self::raw(sub_mod_raw(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Mul<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn mul(self, rhs: V) -> Self::Output {
            Self::raw(mul_mod_u32(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Div<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn div(self, rhs: V) -> Self::Output { self * rhs.into().inv() }
    }

    impl <V: Into<ModIntBase<M>>, M: Modulus> AddAssign<V> for ModIntBase<M> {
        #[inline]
        fn add_assign(&mut self, rhs: V) { *self = *self + rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> SubAssign<V> for ModIntBase<M> {
        #[inline]
        fn sub_assign(&mut self, rhs: V) { *self = *self - rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> MulAssign<V> for ModIntBase<M> {
        #[inline]
        fn mul_assign(&mut self, rhs: V) { *self = *self * rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> DivAssign<V> for ModIntBase<M> {
        #[inline]
        fn div_assign(&mut self, rhs: V) { *self = *self / rhs; }
    }

    impl <M: Modulus> std::iter::Sum for ModIntBase<M> {
        #[inline] fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::raw(0), Add::add)
        }
    }
    impl <M: Modulus> std::iter::Product for ModIntBase<M> {
        #[inline] fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(1.into(), Mul::mul)
        }
    }
    impl<'a, M: Modulus> std::iter::Sum<&'a Self> for ModIntBase<M> {
        #[inline] fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> ModIntBase<M> {
            iter.fold(Self::raw(0), |a, &b| a + b)
        }
    }
    impl<'a, M: Modulus> std::iter::Product<&'a Self> for ModIntBase<M> {
        #[inline] fn product<I: Iterator<Item = &'a Self>>(iter: I) -> ModIntBase<M> {
            iter.fold(1.into(), |a, &b| a * b)
        }
    }

    macro_rules! const_modulus {
        ($mint: ident, $name: ident, $modulus: expr) => {
            #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
            pub enum $name {}
            impl Modulus for $name {
                #[inline(always)] fn get_modulus() -> u32 { $modulus }
            }
            pub type $mint = ModIntBase<$name>;
        }
    }

    macro_rules! dynamic_modulus {
        ($mint: ident, $name: ident, $modulus: ident) => {
            static $modulus: crate::Unsync<Cell<u32>> = crate::Unsync(Cell::new(0));
            #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
            pub enum $name {}
            impl Modulus for $name {
                fn get_modulus() -> u32 { $modulus.0.get() }
            }
            impl $name {
                pub fn set_modulus(val: u32) { $modulus.0.set(val) }
            }
            pub type $mint = ModIntBase<$name>;
        }
    }

    const_modulus!(ModInt998_244_353, Mod998_244_353, 998_244_353);
    const_modulus!(ModInt1_000_000_007, Mod1_000_000_007, 1_000_000_007);
    dynamic_modulus!(DynamicModInt, DynamicModulus, DYNAMIC_MODULUS);
}

use crate::modint::*;
type ModInt = ModInt998_244_353;
// type ModInt = ModInt1_000_000_007;
// const_modulus!(ModInt, DefaultModulus, 1_000_000_009);
// type ModInt = DynamicModInt;

fn mod_factorials(maxn: usize) -> Vec<ModInt> {
    let mut res = vec![ModInt::default(); maxn+1];
    res[0] = 1.into();
    for i in 1..=maxn {
        res[i] = res[i-1] * i
    }
    return res;
}

struct ModCombinatorics {
    factorials: Vec<ModInt>,
    inv_factorials: Vec<ModInt>
}
impl ModCombinatorics {
    fn new(maxn: usize) -> Self {
        let factorials = mod_factorials(maxn);
        let mut inv = vec![ModInt::default(); maxn+1];
        inv[maxn] = factorials[maxn].inv();
        for i in (1..=maxn).rev() {
            inv[i-1] = inv[i] * i;
        }
        Self { factorials, inv_factorials: inv }
    }
    #[inline]
    fn factorial(&self, n: usize) -> ModInt { self.factorials[n] }
    #[inline]
    fn inv_factorial(&self, n: usize) -> ModInt { self.inv_factorials[n] }
    fn P(&self, n: usize, k: usize) -> ModInt {
        if k > n { ModInt::raw(0) } else { self.factorial(n) * self.inv_factorial(n-k) }
    }
    fn C(&self, n: usize, k: usize) -> ModInt {
        if k > n { ModInt::raw(0) } else { self.factorial(n) * self.inv_factorial(k) * self.inv_factorial(n-k) }
    }

    // multi-choose, be sure to adjust maxn accordingly
    fn M(&self, n: usize, k: usize) -> ModInt {
        if k == 0 { 1.into() } else { self.C(n + k - 1, k) }
    }
}

#[allow(non_snake_case, non_upper_case_globals)]
fn main() {
    let num_cases: usize = 1;//read();

    for _case_num in 1..=num_cases {
        let n = read!(usize);
        let x = read!(usize);

        let mc = ModCombinatorics::new(n);

        let pow = veci!(x+1, i: ModInt::pow_vec(mi(i), n));

        struct Dp<'a> {
            D: Vec<Vec<Cell<Option<ModInt>>>>,
            f: &'a dyn Fn(&Dp, usize, usize) -> ModInt
        }

        let dp = Dp {
            D: vec![vec![Cell::new(None); x+1]; n+1],
            f: &|dp, i, j| {
                match dp.D[i][j].get() {
                    Some(x) => x,
                    None => {
                        let res = if j < i { pow[j][i] - pow[j-1][i] } else {
                            (2..=i).map(|k| (dp.f)(dp, k, j-(i-1)) * mc.C(i, k) * pow[i-1][i-k]).sum()
                        };

                        dp.D[i][j].set(Some(res));
                        res
                    }
                }
            }
        };

        let mut ans = mi(0);
        for i in 1..=x { ans += (dp.f)(&dp, n, i); }
        println!(ans);
    }

    out_flush();
}


use std::io;

fn main() {
    let mut s = String::new();
    io::stdin().read_line(&mut s).unwrap();
    let arr : Vec<i64> = s.split_whitespace().map(|s| s.parse().unwrap()).collect();
    let (mut x, mut y, mut cnt) = (arr[0], arr[1], 0);
    loop {
        cnt += 1;
        x *= 3;
        y *= 2;
        if x > y {
            println!("{}", cnt);
            break;
        }
    };
}


#[allow(unused_imports)]
use std::io;
use std::cmp::{min, max};
pub struct Scanner<B> {
    reader: B,
    buffer: Vec<String>,
}

impl<B: io::BufRead> Scanner<B> {
    pub fn new(reader: B) -> Scanner<B> {
        Scanner {
            reader: reader,
            buffer: Vec::new(),
        }
    }

    /// Use "turbofish" syntax next::<T>() to select data type of next token.
    pub fn next<T: ::std::str::FromStr>(&mut self) -> T
    where
        T::Err: ::std::fmt::Debug,
    {
        if let Some(front) = self.buffer.pop() {
            front.parse::<T>().expect(&front)
        } else {
            let mut input = String::new();
            self.reader.read_line(&mut input).expect("Line not read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
            self.next()
        }
    }

    pub fn next_vec<T: ::std::str::FromStr>(&mut self, len: usize) -> Vec<T>
    where
        T::Err: ::std::fmt::Debug,
    {
        (0..len).map(|_| self.next::<T>()).collect::<Vec<T>>()
    }
}

fn main1() {
    let stdin = io::stdin();
    let mut input = Scanner::new(stdin.lock());
    let mut a = input.next::<i64>();
    let mut b = input.next::<i64>();
    let mut answer = 0;
    while a <= b {
        a *= 3;
        b *= 2;
        answer += 1;
    }
    println!("{}", answer);
}

fn main() {
    std::thread::Builder::new().stack_size(50 << 20)
        .spawn(main1).unwrap().join().unwrap();
}


fn main() {
    let mut reader = scanner::TokenReader::new();
    let mut a: usize = reader.next();
    let mut b: usize = reader.next();
    let mut n = 0;

    while a <= b {
        a *= 3;
        b *= 2;
        n += 1;
    }
    println!("{}", n);
}

// ---------- Begin Scanner ----------
#[allow(dead_code)]
mod scanner {
    use std::fmt::Debug;
    use std::str::FromStr;

    pub struct TokenReader {
        reader: std::io::Stdin,
        tokens: Vec<String>,
        index: usize,
    }

    impl TokenReader {
        pub fn new() -> Self {
            Self {
                reader: std::io::stdin(),
                tokens: Vec::new(),
                index: 0,
            }
        }

        pub fn next<T>(&mut self) -> T
        where
            T: FromStr,
            T::Err: Debug,
        {
            if self.index >= self.tokens.len() {
                self.load_next_line();
            }
            self.index += 1;
            self.tokens[self.index - 1].parse().unwrap()
        }

        pub fn vector<T>(&mut self) -> Vec<T>
        where
            T: FromStr,
            T::Err: Debug,
        {
            if self.index >= self.tokens.len() {
                self.load_next_line();
            }
            self.index = self.tokens.len();
            self.tokens.iter().map(|tok| tok.parse().unwrap()).collect()
        }

        pub fn load_next_line(&mut self) {
            let mut line = String::new();
            self.reader.read_line(&mut line).unwrap();

            self.tokens = line.split_whitespace().map(String::from).collect();
            self.index = 0;
        }
    }
}
// ---------- End Scanner ----------


fn main() {
    let mut buf  = String::new();

    std::io::stdin().read_line(&mut buf).unwrap();

    let mut bears_weight: Vec<u32> = buf
        .split_ascii_whitespace()
        .map(|x| x.parse().unwrap())
        .collect();

    let mut count = 0;
    while bears_weight[0] <= bears_weight[1] {
        count += 1;
        bears_weight[0] *= 3;
        bears_weight[1] *= 2;
    }
    println!("{}", count);
}


#[allow(unused_imports)]
use std::cmp::{min,max};
use std::io::{BufWriter, stdin, stdout, Write};

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>
}
impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scan = Scanner::default();
    let out = &mut BufWriter::new(stdout());

    let mut l: u64 = scan.next();
    let mut b: u64 = scan.next();

    for i in 1..
    {
        l *= 3u64;
        b *= 2u64;
        if l > b
        {
            writeln!(out, "{}", i).ok();
            break;
        }
    }
}


use std::io::{self, Write};

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout.lock());

    let a;
    let b;

    unsafe {
        let input: Vec<_> = scan
            .next()
            .split_ascii_whitespace()
            .map(|s| s.parse::<i32>().unwrap())
            .collect();

        let ptr = input.as_ptr();
        a = *ptr as f64;
        b = *ptr.offset(1) as f64;
    }

    writeln!(
        out,
        "{}",
        ((a.ln() - b.ln()) / 0.405465108108164f64).abs() as i32 + 1
    )
    .ok();
}

pub struct Scanner<T> {
    reader: T,
}

impl<R: io::BufRead> Scanner<R> {
    pub fn new(reader: R) -> Self {
        Self { reader }
    }

    pub fn next(&mut self) -> String {
        loop {
            let mut input = String::new();
            self.reader.read_line(&mut input).unwrap();

            return input.trim().to_owned();
        }
    }
}


fn read_vec() -> Vec<u16> {
    let mut buffer: String = String::new();
    std::io::stdin().read_line(&mut buffer).expect("Error");
    buffer
        .split_whitespace()
        .map(|brother|
            brother.parse::<u16>().expect("Error"))
        .collect()
}

fn main() {
    let (mut a, mut b): (u16, u16) = {
        let brothers: Vec<u16> = read_vec();
        (brothers[0], brothers[1])
    };

    let mut years: u8 = 0;
    while a <= b {
        a *= 3;
        b *= 2;
        years += 1;
    }

    println!("{}", years);
}


use std::io::{self, Stdin};
use std::str::{self, FromStr};
use std::error::Error;

fn exec() {
    let mut sc = Scanner::new();
    let mut a: u64 = sc.ne();
    let mut b: u64 = sc.ne();
    for i in 0..100 {
        a *= 3;
        b *= 2;
        if a > b {
            println!("{}", i + 1);
            break;
        }
    }
}

fn main() {
    const STACK: usize = 16 * 1024 * 1024;
    let _ = std::thread::Builder::new()
        .stack_size(STACK)
        .spawn(|| { exec(); })
        .unwrap()
        .join()
        .unwrap();
}

#[allow(dead_code)]
struct Scanner {
    stdin: Stdin,
    id: usize,
    buf: Vec<u8>,
}

#[allow(dead_code)]
impl Scanner {
    fn new() -> Scanner {
        Scanner {
            stdin: io::stdin(),
            id: 0,
            buf: Vec::new(),
        }
    }
    fn next_line(&mut self) -> Option<String> {
        let mut res = String::new();
        match self.stdin.read_line(&mut res) {
            Ok(0) => None,
            Ok(_) => Some(res),
            Err(why) => panic!("error in read_line: {}", why.description()),
        }
    }
    fn next<T: FromStr>(&mut self) -> Option<T> {
        while self.buf.len() == 0 {
            self.buf = match self.next_line() {
                Some(r) => {
                    self.id = 0;
                    r.trim().as_bytes().to_owned()
                }
                None => return None,
            };
        }
        let l = self.id;
        assert!(self.buf[l] != b' ');
        let n = self.buf.len();
        let mut r = l;
        while r < n && self.buf[r] != b' ' {
            r += 1;
        }
        let res = match str::from_utf8(&self.buf[l..r]).ok().unwrap().parse::<T>() {
            Ok(s) => Some(s),
            Err(_) => {
                panic!("parse error, {:?}",
                       String::from_utf8(self.buf[l..r].to_owned()))
            }
        };
        while r < n && self.buf[r] == b' ' {
            r += 1;
        }
        if r == n {
            self.buf.clear();
        } else {
            self.id = r;
        }
        res
    }
    fn ne<T: FromStr>(&mut self) -> T {
        self.next::<T>().unwrap()
    }
}


use std::io::BufRead;

const MOD: i64 = 1_000_000_007;

fn power(a: i64, p: i64) -> i64 {
    if p == 0 {
        return 1;
    }
    let mut res = power(a, p / 2);
    res = (res * res) % MOD;
    if p % 2 != 0 {
        res = (res * a) % MOD;
    }
    res
}

fn solve(n: i64, m: i64) -> i64 {
    power((power(2, m) + MOD - 1) % MOD, n)
}

fn main() {
    let stdin = std::io::stdin();
    let mut handle = stdin.lock();
    let mut buf = String::new();
    handle.read_line(&mut buf).unwrap();
    let mut it = buf.split_whitespace();
    let (n, m): (i64, i64) = (
        it.next().unwrap().parse().unwrap(),
        it.next().unwrap().parse().unwrap(),
    );
    println!("{}", solve(n, m));
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_power() {
        assert_eq!(power(0, 0), 1);
        assert_eq!(power(2, 1), 2);
        assert_eq!(power(2, 2), 4);
        assert_eq!(power(2, 3), 8);
    }

    #[test]
    fn test_solve() {
        assert_eq!(solve(1, 3), 7);
        assert_eq!(solve(2, 2), 9);
        assert_eq!(solve(1_000_000_000, 1_000_000_000), 751201557);
    }
}


// ---------- begin ModInt ----------
const MOD: u32 = 1_000_000_007;

#[derive(Clone, Copy)]
struct ModInt(u32);

impl std::ops::Add for ModInt {
    type Output = ModInt;
    fn add(self, rhs: ModInt) -> Self::Output {
        let mut d = self.0 + rhs.0;
        if d >= MOD {
            d -= MOD;
        }
        ModInt(d)
    }
}

impl std::ops::AddAssign for ModInt {
    fn add_assign(&mut self, rhs: ModInt) {
        *self = *self + rhs;
    }
}

impl std::ops::Sub for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: ModInt) -> Self::Output {
        let mut d = self.0 + MOD - rhs.0;
        if d >= MOD {
            d -= MOD;
        }
        ModInt(d)
    }
}

impl std::ops::SubAssign for ModInt {
    fn sub_assign(&mut self, rhs: ModInt) {
        *self = *self - rhs;
    }
}

impl std::ops::Mul for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: ModInt) -> Self::Output {
        ModInt((self.0 as u64 * rhs.0 as u64 % MOD as u64) as u32)
    }
}

impl std::ops::MulAssign for ModInt {
    fn mul_assign(&mut self, rhs: ModInt) {
        *self = *self * rhs;
    }
}

impl std::ops::Neg for ModInt {
    type Output = ModInt;
    fn neg(self) -> Self::Output {
        ModInt(if self.0 == 0 {0} else {MOD - self.0})
    }
}

/*
impl std::fmt::Display for ModInt {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}
*/

#[allow(dead_code)]
impl ModInt {
    pub fn new(n: u32) -> ModInt {
        ModInt(n % MOD)
    }
    pub fn zero() -> ModInt {
        ModInt(0)
    }
    pub fn one() -> ModInt {
        ModInt(1)
    }
    pub fn pow(self, mut n: u32) -> ModInt {
        let mut t = ModInt::one();
        let mut s = self;
        while n > 0 {
            if n & 1 == 1 {
                t *= s;
            }
            s *= s;
            n >>= 1;
        }
        t
    }
    pub fn inv(self) -> ModInt {
        self.pow(MOD - 2)
    }
    pub fn comb(n: u32, k: u32) -> ModInt {
        if k > n {
            return ModInt::zero();
        }
        let k = std::cmp::min(k, n - k);
        let mut nu = ModInt::one();
        let mut de = ModInt::one();
        for i in 0..k {
            nu *= ModInt(n - i);
            de *= ModInt(i + 1);
        }
        nu * de.inv()
    }
}

#[allow(dead_code)]
struct Precalc {
    inv: Vec<ModInt>,
    fact: Vec<ModInt>,
    ifact: Vec<ModInt>,
}

#[allow(dead_code)]
impl Precalc {
    pub fn new(n: usize) -> Precalc {
        let mut inv = vec![ModInt::one(); n + 1];
        let mut fact = vec![ModInt::one(); n + 1];
        let mut ifact = vec![ModInt::one(); n + 1];
        for i in 2..(n + 1) {
            inv[i] = -inv[MOD as usize % i] * ModInt(MOD / i as u32);
            fact[i] = fact[i - 1] * ModInt(i as u32);
            ifact[i] = ifact[i - 1] * inv[i];
        }
        Precalc {
            inv: inv,
            fact: fact,
            ifact: ifact,
        }
    }
    pub fn inv(&self, n: usize) -> ModInt {
        self.inv[n]
    }
    pub fn fact(&self, n: usize) -> ModInt {
        self.fact[n]
    }
    pub fn ifact(&self, n: usize) -> ModInt {
        self.ifact[n]
    }
    pub fn comb(&self, n: usize, k: usize) -> ModInt {
        if k > n {
            return ModInt::zero();
        }
        self.fact[n] * self.ifact[k] * self.ifact[n - k]
    }
}
// ---------- end ModInt ----------
//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

// ここまで

fn run() {
    input! {
        n: u32,
        m: u32,
    }
    let ans = (ModInt(2).pow(m) - ModInt(1)).pow(n);
    println!("{}", ans.0);
}

fn main() {
    run();
}


use std::io::{self, Read};
use std::cmp;

static M: i64 = 1000_000_007;

fn exponentiate( base: i64, mut exponent: i64 ) -> i64 {
    let mut ans = 1;
    let mut accum = base;
    while exponent != 0 {
        if exponent & 1 != 0 {
            ans = (ans * accum) % M;
        }
        accum = (accum * accum) % M;
        exponent = exponent >> 1;
    }
    ans
}

fn main() -> () {

    let mut buffer = String::new();

    {
        let stdin = io::stdin();
        let mut handle = stdin.lock();
        handle.read_to_string(&mut buffer).expect("stdin");
    }

    let mut arr : Vec<_> = buffer.split_whitespace().map(|x| x.parse::<i64>().unwrap() ).collect();

    let n = arr[0];
    let m = arr[1];

    let ans = exponentiate((exponentiate(2,m)-1+M)%M,n);

    println!("{}",ans);

}

#[test]
fn test(){
    assert_eq!(27, exponentiate(3,3));
}


#![allow(unused_imports)]
#![allow(unused_macros)]
use std::io::{StdinLock, stdin, BufRead};
use std::collections::*;
use std::cmp::*;

fn scan_helper(lock : &mut StdinLock) -> String {
    let mut buffer = String::new();
    lock.read_line(&mut buffer).ok();
    buffer
}

macro_rules! scan {
    ($lock:ident, $t:ty) => ({
        scan_helper(&mut $lock).split_whitespace()
            .next().unwrap()
            .parse::<$t>().unwrap()
    });
    ($lock:ident, $($t:ty),+) => ({
        let buffer = scan_helper(&mut $lock);
        let mut iter = buffer.split_whitespace();
        ($(
            {
                iter.next().unwrap()
                    .parse::<$t>().unwrap()
            },
        )+)
    })
}

macro_rules! scan_iter {
    ($lock:ident, $t:ty) => ({
        scan_helper(&mut $lock).split_whitespace()
            .map(|x| x.parse::<$t>().expect("scan_iter"))
            .collect()
    })
}

trait Ext {
    fn idx(&self) -> usize;
    fn num(&self) -> i64;
}

macro_rules! ext {
    ($t:ty) => (
        impl Ext for $t {
            #[inline]
            fn idx(&self) -> usize {
                *self as usize
            }

            #[inline]
            fn num(&self) -> i64 {
                *self as i64
            }
        }
    )
}
ext!(i64);
ext!(usize);

macro_rules! derive_regular {
    ($t:ty) => (
        impl Ord for $t {
            fn cmp(&self, other : &$t) -> Ordering {
                self.partial_cmp(other).unwrap()
            }
        }
        impl PartialEq for $t {
            fn eq(&self, other : &$t) -> bool {
                self.cmp(other) == Ordering::Equal
            }
        }
        impl Eq for $t {}
    )
}

fn main() {
    let stdin = stdin();
    let mut s = stdin.lock();
    let x : Vec<_> = scan!(s, String).into_bytes();
    let mut j = x.len() - 1;

    while j > 0 && x[j] == b'0' {
        j -= 1;
    }

    let mut i = 0;
    let mut result = true;
    while i < j {
        if x[i] != x[j] {
            result = false;
            break;
        }
        i += 1;
        j -= 1;
    }

    if result {
        println!("YES");
    } else {
        println!("NO");
    }
}


use std::io;
use std::str::FromStr;

use std::io::prelude::*;
use std::io::BufReader;
use std::cmp::{max, min};

fn get_line() -> String {
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    input
}

fn get_vec<T>(s: String) -> Vec<T>
    where T: FromStr,
          <T as FromStr>::Err: std::fmt::Debug,
{
    s.split_whitespace().map(|k| k.parse().unwrap()).collect()
}

fn main() {
    let x = get_line().trim().to_string();

    let x: String = x.chars().rev().skip_while(|&c| c == '0').collect();

    let ans = x.chars().zip(x.chars().rev()).all(|(c1, c2)| c1 == c2);

    if ans {
        println!("YES");
    } else {
        println!("NO");
    };
}


#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(overflowing_literals)]
#![allow(unused_must_use)]

use std::collections::*;
use std::io::*;
use std::cmp::{min, max};
use std::f64::consts::*;
use std::mem::swap;
use std::fs::File;
use std::rc::*;
use std::ascii::*;
use std::ops::*;

const INF: i32 = std::i32::MAX;
const LINF: i64 = std::i64::MAX;
const MOD: usize = 1000000007;

#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone)]
struct Pair<A: Eq + Ord + Copy + Clone, B: Eq + Ord + Copy + Clone>(A, B);

struct Input<Buf: BufRead>
{
	buffer: Buf
}

impl<Buf: BufRead> Input<Buf>
{
	fn read_line(&mut self) -> String {
		let mut v = Vec::new();
		let mut x = [255u8];
		self.buffer.read(&mut x).expect("EOF");
		while x[0] < b' ' && x[0] != 255u8 {
			x[0] = 255u8;
			self.buffer.read(&mut x).expect("EOF");
		}
		while x[0] >= b' ' && x[0] != 255u8 {
			v.push(x[0]);
			x[0] = 255u8;
			self.buffer.read(&mut x).expect("EOF");
		}
		String::from_utf8(v).unwrap()
	}

	fn read_word(&mut self) -> String {
		let mut v = Vec::new();
		let mut x = [255u8];
		self.buffer.read(&mut x).expect("EOF");
		while x[0] <= b' ' && x[0] != 255u8 {
			x[0] = 255u8;
			self.buffer.read(&mut x).expect("EOF");
		}
		while x[0] > b' ' && x[0] != 255u8 {
			v.push(x[0]);
			x[0] = 255u8;
			self.buffer.read(&mut x).expect("EOF");
		}
		String::from_utf8(v).unwrap()
	}
	#[inline]
	fn read_int(&mut self) -> i32 {
		self.read_word().parse::<i32>().expect("Parsing error")
	}
	#[inline]
	fn read_long(&mut self) -> i64 {
		self.read_word().parse::<i64>().expect("Parsing error")
	}
	#[inline]
	fn read_usize(&mut self) -> usize {
		self.read_word().parse::<usize>().expect("Parsing error")
	}
	#[inline]
	fn read_double(&mut self) -> f64 {
		self.read_word().parse::<f64>().expect("Parsing error")
	}
}
macro_rules! read {
    () => {};
	($inf:ident,$($t:ty),*) => ({($({$inf.read_word().parse::<$t>().expect("Parsing error")}),*)});
}
fn gcd<T: RemAssign + Ord + From<i32> + Copy + Clone>(x: T, y: T) -> T {
	let (mut a, mut b) = (x, y);
	while b > T::from(0) {
		a %= b;
		swap(&mut a, &mut b);
	}
	a
}

fn main() {
	match std::env::var("home") {
		Ok(_x) => {
			let mut inf = Input {
				buffer: BufReader::new(File::open("input.txt").expect("File not found"))
			};
			let mut ouf = BufWriter::new(stdout());
			solve(&mut inf, &mut ouf);
		}
		Err(_e) => {
			let mut inf = Input { buffer: BufReader::new(stdin()) };
			let mut ouf = BufWriter::new(stdout());
			solve(&mut inf, &mut ouf);
		}
	}
}

fn solve<Inner: BufRead, Output: Write>(inf: &mut Input<Inner>, ouf: &mut Output)
{
	let mut x = read!(inf,usize);
	while x % 10 == 0 {
		x /= 10;
	}
	let mut y = format!("{}", x).as_bytes().to_vec();
	y.reverse();
	if format!("{}", x) == String::from_utf8(y).unwrap() {
		writeln!(ouf, "YES");
	} else {
		writeln!(ouf, "NO");
	}
}


use std::io;

#[allow(dead_code)]
fn main() {
    let mut input = "".split_ascii_whitespace();
    let mut read = || loop {
        if let Some(word) = input.next() {
            break word;
        }
        input = {
            let mut input = "".to_owned();
            io::stdin().read_line(&mut input).unwrap();
            if input.is_empty() {
                panic!("reached EOF");
            }
            Box::leak(input.into_boxed_str()).split_ascii_whitespace()
        };
    };
    macro_rules! read(($ty:ty) => (read().parse::<$ty>().unwrap()));

    let n = read!(usize);
    let m = read!(usize);
    let mut sa = vec!["".to_string(); 0];
    for _ in 0..n {
        sa.push(read!(String));
    }
    let mut ca = vec![vec![' '; 0]; n];
    for i in 0..n {
        ca[i] = sa[i].chars().collect::<Vec<char>>();
    }
    let mut ba = vec![vec![false; m]; n];

    for i in 0..n {
        for j in 0..m {
            if ca[i][j] != 'P' {
                continue;
            }
            if i > 0 && ca[i - 1][j] == 'W' {
                ba[i - 1][j] = true;
            }
            if i < n - 1 && ca[i + 1][j] == 'W' {
                ba[i + 1][j] = true;
            }
            if j > 0 && ca[i][j - 1] == 'W' {
                ba[i][j - 1] = true;
            }
            if j < m - 1 && ca[i][j + 1] == 'W' {
                ba[i][j + 1] = true;
            }
        }
    }

    let mut r = 0;
    for i in 0..n {
        for j in 0..m {
            if ba[i][j] {
                r += 1;
            }
        }
    }

    println!("{}", r);
}


#[allow(unused_imports)]
use std::char::*;
#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
use std::io::*;
use std::str::FromStr;

#[allow(unused_macros)]
macro_rules! debug {($($a:expr),*) => {println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);}}
#[allow(unused_macros)]
macro_rules! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; let mut next = || { iter . next ( ) . unwrap ( ) } ; input_inner ! { next , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { let stdin = std :: io :: stdin ( ) ; let mut bytes = std :: io :: Read :: bytes ( std :: io :: BufReader :: new ( stdin . lock ( ) ) ) ; let mut next = move || -> String { bytes . by_ref ( ) . map ( | r | r . unwrap ( ) as char ) . skip_while ( | c | c . is_whitespace ( ) ) . take_while ( | c |! c . is_whitespace ( ) ) . collect ( ) } ; input_inner ! { next , $ ( $ r ) * } } ; }
#[allow(unused_macros)]
macro_rules! input_inner { ( $ next : expr ) => { } ; ( $ next : expr , ) => { } ; ( $ next : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ next , $ t ) ; input_inner ! { $ next $ ( $ r ) * } } ; }
#[allow(unused_macros)]
macro_rules! read_value { ( $ next : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ next , $ t ) ) ,* ) } ; ( $ next : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ next , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ next : expr , chars ) => { read_value ! ( $ next , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ next : expr , usize1 ) => { read_value ! ( $ next , usize ) - 1 } ; ( $ next : expr , $ t : ty ) => { $ next ( ) . parse ::<$ t > ( ) . expect ( "Parse error" ) } ; }

#[derive(PartialEq, PartialOrd)]
pub struct Total<T>(pub T);
impl<T: PartialEq> Eq for Total<T> {}
impl<T: PartialOrd> Ord for Total<T> { fn cmp(&self, other: &Total<T>) -> std::cmp::Ordering { self.0.partial_cmp(&other.0).unwrap() }}

#[allow(dead_code)]
const MAX:usize = 100006;
#[allow(dead_code)]
const MOD:i64 = 1e9 as i64 + 7;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().split_whitespace()
        .map(|e| e.parse().ok().unwrap()).collect()
}

#[allow(unused_imports)]
use std::f64;

fn min<T: PartialOrd>(a:T, b:T) -> T {
    if a < b { a }
    else { b }
}

use std::hash::Hash;
fn inc<T: Hash+Ord>(map:&mut BTreeMap<T,i64>, key:T) {
    let count = map.entry(key).or_insert(0);
    *count += 1;
}

fn main() {
    input!{n:usize, s:chars};
    let mut s = s;

    let mut ans = 0;

    loop {
        if s.len() == 1 { break; }
        let mut f = vec![];
        for i in 0..s.len() {
            if i==0 {
                if s[i] as u8 == s[i+1] as u8 + 1 {
                    f.push((s[i],i));
                }
            }
            else if i == s.len()-1 {
                if s[i] as u8 == s[i-1] as u8 + 1 {
                    f.push((s[i],i));
                }
            }
            else {
                if s[i] as u8 == s[i-1] as u8 +1 {
                    f.push((s[i],i));
                }
                if s[i] as u8 == s[i+1] as u8 + 1 {
                    f.push((s[i],i));
                }
            }
        }
        f.sort();
        f.reverse();
        //debug!(f);
        if f.len() == 0 { break; }
        let rem = f[0].1;
        let mut t = vec![];
        for i in 0..s.len() {
            if i != rem {
                t.push(s[i]);
            }
        }
        //debug!(t);
        ans += 1;
        s = t;
    }

    println!("{}", ans);

}


use std::io::stdin;
#[allow(unused_imports)]
use std::iter::FromIterator;
#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn can_remove(index: usize, phrase: &mut Vec<char>) -> bool {
    let phrase_length = phrase.len();
    let (current, previous, next) = (
        phrase[index] as i32,
        if index == 0 {
            phrase[index] as i32
        } else {
            phrase[index - 1] as i32
        },
        if index == (phrase_length - 1) {
            phrase[index] as i32
        } else {
            phrase[index + 1] as i32
        },
    );
    (current as i32 - next as i32) == 1 || (current as i32 - previous as i32) == 1
}

fn try_remove_next<'a>(phrase: &mut Vec<char>) -> bool {
    let mut bigger = 'a' as i32 - 1;
    let mut candidate: usize = 101;
    for (i, charac) in phrase.clone().iter().enumerate() {
        if *charac as i32 > bigger && can_remove(i, phrase) {
            candidate = i;
            bigger = *charac as i32;
        }
    }
    if candidate == 101 {
        false
    } else {
        phrase.remove(candidate);
        true
    }
}
fn main() {
    let mut scan = Scanner::default();
    let _ = scan.next::<usize>();
    let mut stra: Vec<char> = scan.next::<String>().chars().collect();
    let chars: &mut Vec<char> = &mut stra.as_mut();
    let mut totals = 0;
    loop {
        let removed = try_remove_next(chars);
        if removed {
            totals += 1;
        } else {
            break;
        }
    }
    println!("{}", totals)
}


use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut lines = stdin.lock().lines();
    let _ = lines.next().unwrap().unwrap().parse::<i64>().unwrap();
    let s: String = lines.next().unwrap().unwrap();
    println!("{}", s.len() - solve(s, 'a').len());
}

pub fn solve(s: String, ch: char) -> String {
    if &s == "" {
        return "".to_string();
    }
    let mut result = 0;
    let segments = s.split(ch).map(|s| s.to_string()).collect::<Vec<String>>();
    let mut new_string = String::new();
    for segment in segments.iter().cloned() {
        new_string += &solve(segment, (ch as u8 + 1) as char);
        new_string += &ch.to_string();
    }
    new_string.pop();

    let pattern1 = ch.to_string() + &((ch as u8 + 1) as char).to_string();
    let pattern2 = ((ch as u8 + 1) as char).to_string() + &ch.to_string();
    while {
        let len = new_string.len();
        new_string = new_string.replace(&pattern1, &ch.to_string());
        new_string = new_string.replace(&pattern2, &ch.to_string());
        len != new_string.len()
    } {}
    //println!("{} - {}", s, new_string);

    new_string
}


use std::io::stdin;

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}
impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scan = Scanner::default();
    let n = scan.next::<i32>();
    let mut s = scan.next::<String>().into_bytes();
    let mut ans = 0;
    loop {
        let mut ord = Vec::with_capacity(s.len());
        for (pos, val) in s.iter().enumerate() {
            ord.push((val, pos));
        }
        ord.sort();
        ord.reverse();

        let mut del_idx = -1;
        for (_, (_, pos)) in ord.iter().enumerate() {
            let i = *pos as i32;
            if (i > 0 && s[(i - 1) as usize] == s[i as usize] - 1)
                || (i < s.len() as i32 - 1 && s[(i + 1) as usize] == s[i as usize] - 1)
            {
                del_idx = i;
                break;
            }
        }
        if del_idx == -1 {
            break;
        }
        s.remove(del_idx as usize);
        ans += 1;
    }
    println!("{}", ans);
}


#[allow(unused_imports)]
use std::cmp::{Ordering};

#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};

#[allow(unused_imports)]
use std::io::{stdin, stdout, BufWriter, Write};

#[allow(unused_imports)]
use std::iter::FromIterator;

#[allow(unused_macros)]
macro_rules! min {
    ($x: expr) => ($x);
    ($x: expr, $($z: expr),+) => {{
        std::cmp::min($x, min!($($z),*))
    }}
}

#[allow(unused_macros)]
macro_rules! max {
    ($x: expr) => ($x);
    ($x: expr, $($z: expr),+) => {{
        std::cmp::max($x, max!($($z),*))
    }}
}

#[allow(unused_macros)]
macro_rules! get {
    ([$t: ty]) => {
        {
            let mut line = String::new();
            stdin().read_line(&mut line).unwrap();
            line.split_whitespace().map(|t|t.parse::<$t>().unwrap()).collect::<Vec<_>>()
        }
    };
    ([$t: ty];$n: expr) => {
        (0..$n).map(|_|get!([$t])).collect::<Vec<_>>()
    };
    ($t: ty) => {
        {
            let mut line = String::new();
            stdin().read_line(&mut line).unwrap();
            line.trim().parse::<$t>().unwrap()
        }
    };
    ($($t: ty),*) => {
        {
            let mut line = String::new();
            stdin().read_line(&mut line).unwrap();
            let mut iter = line.split_whitespace();
            ($(iter.next().unwrap().parse::<$t>().unwrap(),)*)
        }
    };
    ($t: ty; $n: expr) => {
        (0..$n).map(|_|get!($t)).collect::<Vec<_>>()
    };
    ($($t: ty),*; $n: expr) => {
        (0..$n).map(|_|get!($($t),*)).collect::<Vec<_>>()
    };
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($a:expr),*) => {
        #[cfg(debug_assertions)]
        writeln!(&mut std::io::stderr(), concat!("[DEBUG] ", $(stringify!($a), "={:?} "),*), $($a),*).unwrap();
    }
}

const BIG_STACK_SIZE: bool = true;

#[allow(dead_code)]
fn main() {
    use std::thread;
    if BIG_STACK_SIZE {
        thread::Builder::new()
            .stack_size(32 * 1024 * 1024)
            .name("solve".into())
            .spawn(solve)
            .unwrap()
            .join()
            .unwrap();
    } else {
        solve();
    }
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Rev<T>(pub T);
impl<T: PartialOrd> PartialOrd for Rev<T> {
    fn partial_cmp(&self, other: &Rev<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}
impl<T: Ord> Ord for Rev<T> {
    fn cmp(&self, other: &Rev<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}

fn solve() {
    let out = stdout();
    let mut out = BufWriter::new(out.lock());
    let n = get!(usize);
    let mut s = get!(String).chars().map(|e| e as usize - 'a' as usize).collect::<Vec<_>>();

    loop {
        let mut flag = false;
        let mut j = 0;
        let mut c = 0;
        for i in 0..s.len() {
            if (i>0 && s[i-1]+1==s[i]) || (i<s.len()-1 && s[i+1]+1==s[i]) {
                if c < s[i] {
                    c = s[i];
                    j = i;
                    flag = true;
                }
            }
        }
        if !flag {
            break;
        }
        s.remove(j);
    }
    writeln!(out, "{}", n-s.len()).unwrap();
}


use std::io::stdin;

fn main() {
    let mut s = String::new();
    stdin().read_line(&mut s).unwrap();
    s = String::new();
    stdin().read_line(&mut s).unwrap();
    let mut s: Vec<u8> = s.trim().bytes().collect();
    let mut count: u32 = 0;
    if s.len() != 1 {
        for i in 0..s.len() {
            let mut b = false;
            let mut pos = 0;
            let mut max = 0;
            if (s[0] as i16 - s[1] as i16 == 1) {
                max = s[0];
                b = true;
            }
            for j in 1..s.len() - 1 {
                if (s[j] as i16 - s[j - 1] as i16 == 1 || s[j] as i16 - s[j + 1] as i16 == 1) && (s[j] > max) {
                    pos = j;
                    max = s[j];
                    b = true;
                }
            }
            if (s[s.len() - 1] as i16 - s[s.len() - 2] as i16 == 1) && (s[s.len() - 1] > max) {
                pos = s.len() - 1;
                max = s[s.len() - 1];
                b = true;
            }
            if b {
                count += 1;
                s.remove(pos);
                if s.len() == 1 {
                    break;
                }
            } else { break; }
        }
    }
    println!("{}", count);
}


use std::io::stdin;

#[derive(Default)]
struct Scanner {
    buf: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed read");
            self.buf = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scan = Scanner::default();
    let _n = scan.next::<usize>();
    let mut s: Vec<char> = scan.next::<String>().chars().collect();
    let mut ans = 0;
    loop {
        let mut ord: Vec<(char, usize)> = s.iter().enumerate().map(|(i, &c)| (c, i)).collect();
        ord.sort();
        let mut del_idx = None;
        for &(c, i) in ord.iter().rev() {
            let pc = ((c as u8) - 1) as char;
            if (i > 0 && s[i - 1] == pc) || (i < s.len() - 1 && s[i + 1] == pc) {
                del_idx = Some(i);
                break;
            }
        }
        if let Some(idx) = del_idx {
            s.remove(idx);
            ans += 1;
        } else {
            break;
        }
    }
    println!("{}", ans);
}


//---------- begin union_find ----------
#[allow(dead_code)]
mod union_find {
    pub struct UF {
        p: Vec<i32>,
    }
    impl UF {
        pub fn new(n: usize) -> UF {
            UF {p: vec![-1; n] }
        }
        pub fn init(&mut self) {
            for p in self.p.iter_mut() {
                *p = -1;
            }
        }
        pub fn root(&self, mut x: usize) -> usize {
            while self.p[x] >= 0 {
                x = self.p[x] as usize;
            }
            x
        }
        pub fn same(&self, x: usize, y: usize) -> bool {
            self.root(x) == self.root(y)
        }
        pub fn unite(&mut self, x: usize, y: usize) -> Option<(usize, usize)> {
            let mut x = self.root(x);
            let mut y = self.root(y);
            if x == y {
                return None;
            }
            if self.p[x] > self.p[y] {
                std::mem::swap(&mut x, &mut y);
            }
            self.p[x] += self.p[y];
            self.p[y] = x as i32;
            Some((x, y))
        }
        pub fn parent(&self, x: usize) -> Option<usize> {
            let p = self.p[x];
            if p >= 0 {
                Some(p as usize)
            } else {
                None
            }
        }
        pub fn get_size(&self, x: usize) -> usize {
            let r = self.root(x);
            (-self.p[r]) as usize
        }
    }
}
//---------- end union_find ----------

//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, bytes) => {
        read_value!($iter, String).bytes().collect::<Vec<u8>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

//

fn run() {
    input! {
        n: usize,
        m: usize,
        e: [(usize1, usize1); m],
    }
    let mut e = e;
    for e in e.iter_mut() {
        if e.1 < e.0 {
            *e = (e.1, e.0);
        }
    }
    e.sort();
    let mut deg = vec![0; n];
    for &(a, b) in e.iter() {
        deg[a] += 1;
        deg[b] += 1;
    }
    let mut ans = vec![n; n];
    for i in 0..n {
        if deg[i] == n - 1 {
            ans[i] = 1;
        }
    }
    let mut u = union_find::UF::new(n);
    for &(a, b) in e.iter() {
        if deg[a] != n - 1 && deg[b] != n - 1 {
            u.unite(a, b);
        }
    }
    let mut id = 0;
    let mut add = 2;
    for i in 0..n {
        if deg[i] != n - 1 && i == u.root(i) {
            ans[i] = id;
            id += add;
            add = 1;
        }
    }
    if id > 3 {
        println!("No");
        return;
    }
    for i in 0..n {
        for j in (i + 1)..n {
            let x = u.root(i);
            let y = u.root(j);
            if ans[x] == ans[y] || ans[x] == ans[y] + 1 || ans[x] + 1 == ans[y] {
                if e.binary_search(&(i, j)).is_err() {
                    println!("No");
                    return;
                }
            }
        }
    }
    println!("Yes");
    let mut s = String::new();
    let op: Vec<char> = "abc".chars().collect();
    for i in 0..n {
        s.push(op[ans[u.root(i)]]);
    }
    println!("{}", s);
}

fn main() {
    run();
}


fn main() {
    use std::io::prelude::*;
    use std::io;

    let mut input = String::new();
    io::stdin().read_to_string(&mut input).unwrap();

    let necklace: Vec<_> = input.trim().chars().map(|c| {
        match c {
            '-' => Elem::Link,
            'o' => Elem::Pearl,
            _ => panic!("Invalid input"),
        }
    }).collect();

    let link_pearl_sums = necklace.iter().fold((0, 0), |acc, &e| {
        match e {
            Elem::Link => (acc.0 + 1, acc.1),
            Elem::Pearl => (acc.0, acc.1 + 1),
        }
    });

    let ans = link_pearl_sums.1 == 0 || link_pearl_sums.0 % link_pearl_sums.1 == 0;

    if ans {
        println!("YES");
    } else {
        println!("NO");
    }
}

#[derive(Clone, Copy)]
enum Elem {
    Link,
    Pearl
}


// Try Codeforces
// author: Leonardone @ NEETSDKASU

fn main() {
    let mut stdin = String::new();
    std::io::Read::read_to_string(
        &mut std::io::stdin(),
        &mut stdin).unwrap();
    let mut stdin = stdin.split_whitespace();
    let mut get = || stdin.next().unwrap();
    macro_rules! get {
        () => (get!(i64));
        ($t:ty) => (get().parse::<$t>().unwrap());
    }

    let n = get().as_bytes();

    let mut p = 0;
    let mut s = 0;
    for &c in n {
        if c == b'o' {
            p += 1;
        } else {
            s += 1;
        }
    }

    if p < 2 || s == 0 {
        println!("YES");
        return;
    }

    if s % p == 0 {
        println!("YES");
    } else {
        println!("NO");
    }

}


use std::io;

macro_rules! debug_println {
    ($( $args:expr ),*) => { if cfg!(debug_assertions) { println!( $( $args ),* ); }}
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let (l, mut p) = buf.chars().fold((0, 0), |mut cnt, v| {
        match v {
            '-' => cnt.0 += 1,
            'o' => cnt.1 += 1,
            _ => (),
        }
        cnt
    });
    if p == 0 {
        p = 1
    }
    debug_println!("{:?}", (l, p));
    println!("{}", if l % p == 0 { "YES" } else { "NO" });
}


pub struct Scanner {
  buffer: Vec<String>
}

impl Scanner {
  pub fn new() -> Scanner {
    Scanner { buffer: Vec::new() }
  }

  pub fn next<T: std::str::FromStr>(&mut self) -> T {
    loop {
      if let Some(token) = self.buffer.pop() {
          return token.parse().ok().expect("Failed parse");
      }
      let mut input = String::new();
      std::io::stdin().read_line(&mut input).expect("Failed read");
      self.buffer = input.split_whitespace().rev().map(String::from).collect();
    }
  }
}

fn calculate_divs(mut x: u32) -> Vec<u32> {
  let mut divs: Vec<u32> = Vec::new();
    for p in 2..100_000 {
    if x % p == 0 {
      divs.push(p);
      while x % p == 0 {
        x /= p;
      }
    }
  }
  if x > 1 {
    divs.push(x);
  }
  return divs;
}

const MOD: u64 = 1_000_000_007;

fn bin_pow(mut a: u64, mut n: u64) -> u64 {
  let mut x: u64 = 1;
  while n > 0 {
    if (n & 1) == 1 {
      x = x * a % MOD;
    }
    a = a * a % MOD;
    n >>= 1;
  }
  return x;
}

fn main() {
  let mut scan = Scanner::new();
  let x: u32 = scan.next();
  let n: u64 = scan.next();
  let divs: Vec<u32> = calculate_divs(x);

  let mut ans: u64 = 1;
  for &d in divs.iter() {
    let mut copy_n: u64 = n;
    let mut power: u64 = 0;
    loop {
      copy_n /= d as u64;
      if copy_n == 0 {
        break;
      }
      power += copy_n;
    }
    ans = ans * bin_pow(d as u64, power) % MOD;
  }
  println!("{}", ans);
}


use std::io::{Read,stdin};

const M: i128 = 1_000_000_007;

fn main() {
    let mut buf = String::new();
    stdin().read_to_string(&mut buf).unwrap();
    let mut tok = buf.split_whitespace();
    let mut get = || tok.next().unwrap();
    macro_rules! get {
        ($t:ty) => (get().parse::<$t>().unwrap());
        () => (get!(i128));
    }

    let x = get!();
    let n = get!();

    let mut ps = vec![];
    let mut y = x;
    for i in 2 ..= x {
        if i * i > y {
            break;
        }
        if y % i != 0 {
            continue;
        }
        ps.push(i);
        while y % i == 0 {
            y /= i;
        }
    }
    if y > 1 {
        ps.push(y);
    }
    let mut ans = 1;
    for &p in ps.iter() {
        let mut es = vec![];
        let mut e = p;
        while e <= n {
            es.push(e);
            e *= p;
        }
        let mut t = 0;
        while let Some(e) = es.pop() {
            let c = n / e - t;
            ans = ans * pow(e, c) % M;
            t = n / e;
        }
    }
    println!("{}", ans);
}

fn pow(a: i128, b: i128) -> i128 {
    if b == 0 {
        1
    } else if b % 2 == 0 {
        pow(a * a % M, b / 2)
    } else {
        a * pow(a, b - 1) % M
    }
}


//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

// ここまで

const MOD: u64 = 1_000_000_007;

fn mod_pow(r: u64, mut n: u64) -> u64 {
    let mut t = 1;
    let mut s = r % MOD;
    while n > 0 {
        if n & 1 == 1 {
            t = t * s % MOD;
        }
        s = s * s % MOD;
        n >>= 1;
    }
    t
}

fn run() {
    input! {
        x: u64,
        n: u64,
    }
    let mut ans = 1;
    let mut x = x;
    let mut k = 2;
    while k * k <= x {
        if x % k == 0 {
            while x % k == 0 {
                x /= k;
            }
            let mut t = n;
            let mut c = 0;
            while t > 0 {
                c += t / k;
                t /= k;
            }
            ans = ans * mod_pow(k, c) % MOD;
        }
        k += 1;
    }
    if x > 1 {
        let mut t = n;
        let mut c = 0;
        while t > 0 {
            c += t / x;
            t /= x;
        }
        ans = ans * mod_pow(x, c) % MOD;
    }
    println!("{}", ans);
}

fn main() {
    run();
}


#[allow(unused_imports)]
use std::io::{BufReader, BufWriter, stdin, stdout, Write};
use std::cmp::{min, max};
use std::collections::{VecDeque, HashMap, BTreeMap, HashSet, BTreeSet, BinaryHeap};

const m:i64 = 1000000007;

fn pow(mut x:i64, mut p:i64) -> i64 {
	let mut r:i64 = 1;
	while p > 0 {
		if p % 2 == 1 {
			r = r * x % m;
		}
		x = x * x % m;
		p /= 2;
	}
	return r;
}

fn main() {
	let mut inp = my_input::default();
	let out = &mut BufWriter::new(stdout());
	let mut x:i64 = inp.scan::<i64>();
	let n:i64 = inp.scan::<i64>();
	let mut i = 2 as i64;
	let mut ans = 1 as i64;
	while i * i <= x {
		if x % i == 0 {
			let mut cnt:i64 = 0;
			let mut p:i64 = 1;
			while p <= n / i {
				p *= i;
				cnt += n / p;
			}
			ans = ans * pow(i, cnt) % m;
		}
		while x % i == 0 {
			x /= i;
		}
		i += 1;
	}
	if x > 1 {
		let mut cnt:i64 = 0;
		let mut p:i64 = 1;
		while p <= n / x {
			p *= x;
			cnt += n / p;
		}
		ans = ans * pow(x, cnt) % m;
	}
	writeln!(out, "{}", ans);
}

#[derive(Default)]
struct my_input {
	buffer: Vec<String>
}

impl my_input {
	fn scan<T: std::str::FromStr>(&mut self) -> T {
		loop {
			if let Some(token) = self.buffer.pop() {
				return token.parse().ok().expect("Parsing Error");
			}
			let mut s = String::new();
			stdin().read_line(&mut s).expect("Reading Error");
			self.buffer = s.split_whitespace().rev().map(String::from).collect();
		}
	}
}