結果

問題 No.3315 FPS Game
コンテスト
ユーザー 👑 ArcAki
提出日時 2025-03-01 09:54:20
言語 Rust
(1.83.0 + proconio)
結果
AC  
実行時間 292 ms / 3,250 ms
コード長 30,760 bytes
コンパイル時間 14,043 ms
コンパイル使用メモリ 400,264 KB
実行使用メモリ 38,400 KB
最終ジャッジ日時 2025-10-23 10:10:39
合計ジャッジ時間 20,623 ms
ジャッジサーバーID
(参考情報)
judge1 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 25
権限があれば一括ダウンロードができます

ソースコード

diff #

#[allow(unused_imports)]
use std::{
    cell::RefCell, convert::{Infallible, TryFrom, TryInto as _},
    fmt::{self, Debug, Display, Formatter,},
    fs::{File}, hash::{Hash, Hasher}, iter::{Product, Sum}, marker::PhantomData,
    ops::{Add, AddAssign, Sub, SubAssign, Div, DivAssign, Mul, MulAssign, Neg, },
    str::FromStr, sync::{atomic::{self, AtomicU32, AtomicU64}, Once}, collections::{*},
    mem::{swap}, cmp::{self, Reverse, Ordering, Eq, PartialEq, PartialOrd},
    thread::LocalKey, f64::consts::PI, time::Instant,
    io::{self, stdin, Read, read_to_string, BufWriter, BufReader, stdout, Write},
};
#[allow(unused_imports)]
use proconio::{input, input_interactive, marker::{*}};
#[allow(unused_imports)]
//use rand::{thread_rng, Rng, seq::SliceRandom};
#[allow(unused_imports)]
//use ac_library::{*};

#[allow(dead_code)]
const INF: i64 = 1<<60;
#[allow(dead_code)]
const MOD: i64 = 998244353;
#[allow(dead_code)]
const D: [(usize, usize); 4] = [(1, 0), (0, 1), (!0, 0), (0, !0)];


pub fn safe_mod(mut x: i64, m: i64) ->i64{
    x %= m;
    if x < 0{
        x += m;
    }
    x
}

pub struct Barrett1{
    pub _m: u32,
    pub im: u64,
}

impl Barrett1{
    pub fn new(m: u32)->Barrett1{
        Barrett1{
            _m: m,
            im: (-1i64 as u64/m as u64).wrapping_add(1),
        }
    }

    pub fn umod(&self)->u32{
        self._m
    }

    pub fn mul(&self, a: u32, b: u32)->u32{
        mul_mod(a, b, self._m, self.im)
    }
}

pub fn mul_mod(a: u32, b: u32, m: u32, im: u64)->u32{
    let mut z = a as u64;
    z *= b as u64;
    let x = (((z as u128)*(im as u128))>>64)as u64;
    let mut v = z.wrapping_add(x.wrapping_mul(m as u64))as u32;
    if m <= v{
        v = v.wrapping_add(m);
    }
    v
}

pub fn pow_mod(x: i64, mut n: i64, m: i32)->i64{
    if m==1{
        return 0;
    }
    let _m = m as u32;
    let mut r: u64 = 1;
    let mut y: u64 = safe_mod(x, m as i64) as u64;
    while n != 0{
        if (n & 1) == 1{
            r = (r*y)%(_m as u64);
        }
        y = (y*y)%(_m as u64);
        n >>= 1;
    }
    r as i64
}

pub fn is_prime(n: i32) -> bool{
    let n = n as i64;
    match n {
        _ if n <= 1 => return false,
        2 | 7 | 61 => return true,
        _ if n%2 == 0 => return false,
        _ => {}
    }
    let mut d = n-1;
    while d%2 == 0{
        d /= 2;
    }
    for &a in &[2, 7, 61]{
        let mut t = d;
        let mut y = pow_mod(a, t, n as i32);
        while t != n-1 && y != 1 && y != n-1{
            y = y*y%n; t<<=1;
        }
        if y != n-1 && t%2 == 0{
            return false;
        }
    }
    true
}

pub fn inv_gcd(a: i64, b: i64) -> (i64, i64){
    let a = safe_mod(a, b);
    if a == 0{
        return (b, 0);
    }
    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;
    }
    (s, m0)
}

pub fn primitive_root(m: i32) -> i32{
    match m {
        2 => return 1,
        167772161 => return 3,
        469762049 => return 3,
        754974721 => return 11,
        998244353 => return 3,
        _ => {}
    }
    let mut divs = [0; 20];
    let mut cnt = 0;
    let mut x = (m-1)/2;
    while x%2 == 0{
        x /= 2;
    }
    for i in (3..std::i32::MAX).step_by(2){
        if i as i64 * i as i64 > x as i64 {
            break;
        }
        if x % i == 0{
            divs[cnt] = i;
            cnt += 1;
            while x%i == 0{
                x /= i;
            }
        }
    }
    if x > 1 {
        divs[cnt] = x; cnt += 1;
    }
    let mut g = 2;
    loop {
        if (0..cnt).all(|i| pow_mod(g, ((m-1)/divs[i])as i64, m) != 1){
            break g as i32;
        }
        g += 1;
    }
}

pub type ModInt1000000007 = StaticModInt<Mod1000000007>;
pub type ModInt998244353 = StaticModInt<Mod998244353>;
pub type ModInt = DynamicModInt<DefaultId>;

#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(transparent)]
pub struct StaticModInt<M>{
    val: u32, phantom: PhantomData<fn()->M>,
}

impl<M: Modulus> StaticModInt<M>{
    #[inline(always)]
    pub fn modulus() -> u32{
        M::VALUE
    }

    #[inline]
    pub fn new<T: RemEuclidU32>(val: T)->Self{
        Self::raw(val.rem_euclid_u32(M::VALUE))
    }

    #[inline]
    pub fn raw(val: u32) -> Self{
        Self{
            val,
            phantom: PhantomData,
        }
    }
    #[inline]
    pub fn pow(self, n: u64) -> Self{
        <Self as ModIntBase>::pow(self, n)
    }

    #[inline]
    pub fn val(self) -> u32{
        self.val
    }

    #[inline]
    pub fn inv(self) -> Self{
        if M::HINT_VALUE_IS_PRIME{
            if self.val() == 0{
                panic!("zero division trial");
            }
            self.pow((M::VALUE-2).into())
        } else {
            Self::inv_for_non_prime_modulus(self)
        }
    }
}

impl<M: Modulus> ModIntBase for StaticModInt<M>{
    #[inline(always)]
    fn modulus() -> u32{
        Self::modulus()
    }

    #[inline]
    fn raw(val: u32) -> Self{
        Self::raw(val)
    }

    #[inline]
    fn val(self) -> u32{
        self.val()
    }

    #[inline]
    fn inv(self) -> Self{
        self.inv()
    }
}

pub trait Modulus: 'static + Copy + Eq {
    const VALUE: u32;
    const HINT_VALUE_IS_PRIME: bool;
    fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>>;
}

#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub enum Mod1000000007 {}
impl Modulus for Mod1000000007{
    const VALUE: u32 = 1000000007;
    const HINT_VALUE_IS_PRIME: bool = true;
    fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>> {
        thread_local! {
            static BUTTERFLY_CACHE: RefCell<Option<ButterflyCache<Mod1000000007>>> = RefCell::default();
        }
        &BUTTERFLY_CACHE
    }
}

#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub enum Mod998244353 {}
impl Modulus for Mod998244353 {
    const VALUE: u32 = 998244353;
    const HINT_VALUE_IS_PRIME: bool = true;
    fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>> {
        thread_local! {
            static BUTTERFLY_CACHE: RefCell<Option<ButterflyCache<Mod998244353>>> = RefCell::default();
        }
        &BUTTERFLY_CACHE
    }
}

pub struct ButterflyCache<M>{
    pub sum_e: Vec<StaticModInt<M>>,
    pub sum_ie: Vec<StaticModInt<M>>,
}

#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(transparent)]
pub struct DynamicModInt<I>{
    val: u32, phantom: PhantomData<fn()->I>,
}

impl<I: Id> DynamicModInt<I>{
    #[inline]
    pub fn modulus() -> u32{
        I::companion_barrett().umod()
    }

    #[inline]
    pub fn set_modulus(modulus: u32){
        if modulus == 0{
            panic!("the modulus must not be 0");
        }
        I::companion_barrett().update(modulus);
    }

    #[inline]
    pub fn new<T: RemEuclidU32>(val: T) -> Self {
        <Self as ModIntBase>::new(val)
    }

    #[inline]
    pub fn raw(val: u32) -> Self {
        Self {
            val, phantom: PhantomData,
        }
    }

    #[inline]
    pub fn val(self) -> u32 {
        self.val
    }

    #[inline]
    pub fn pow(self, n: u64) -> Self {
        <Self as ModIntBase>::pow(self, n)
    }

    #[inline]
    pub fn inv(self) -> Self{
        Self::inv_for_non_prime_modulus(self)
    }
}

impl<I: Id> ModIntBase for DynamicModInt<I>{
    #[inline]
    fn modulus() -> u32 {
        Self::modulus()
    }

    #[inline]
    fn raw(val: u32) -> Self{
        Self::raw(val)
    }

    #[inline]
    fn val(self) -> u32 {
        self.val()
    }

    fn inv(self) -> Self {
        self.inv()
    }
}

pub trait Id: 'static + Copy + Eq{
    fn companion_barrett()->&'static Barrett;
}
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub enum DefaultId{}

impl Id for DefaultId{
    fn companion_barrett() -> &'static Barrett {
        static BARRETT: Barrett = Barrett::default();
        &BARRETT
    }
}

pub struct Barrett{
    m: AtomicU32, im: AtomicU64,
}

impl Barrett {
    #[inline]
    pub const fn new(m: u32) -> Self{
        Self {
            m: AtomicU32::new(m), im: AtomicU64::new((-1i64 as u64/m as u64).wrapping_add(1)),
        }
    }

    #[inline]
    const fn default() -> Self{
        Self::new(998244353)
    }

    #[inline]
    fn update(&self, m: u32){
        let im = (-1i64 as u64/m as u64).wrapping_add(1);
        self.m.store(m, atomic::Ordering::SeqCst);
        self.im.store(im, atomic::Ordering::SeqCst);
    }

    #[inline]
    fn umod(&self) -> u32{
        self.m.load(atomic::Ordering::SeqCst)
    }

    #[inline]
    fn mul(&self, a: u32, b: u32) -> u32{
        let m = self.m.load(atomic::Ordering::SeqCst);
        let im = self.im.load(atomic::Ordering::SeqCst);
        mul_mod(a, b, m, im)
    }
}

impl Default for Barrett{
    #[inline]
    fn default() -> Self {
        Self::default()
    }
}

pub trait ModIntBase: Default+FromStr+From<i8>+From<i16>+From<i32>+From<i64>+
From<i64>+From<i128>+From<isize>+From<u8>+From<u16>+From<u32>+From<u64>+
From<u128>+From<usize>+Copy+Eq+Hash+Display+Debug+Neg<Output=Self>+Add<Output=Self>+
Sub<Output=Self>+Mul<Output=Self>+Div<Output=Self>+AddAssign+SubAssign+MulAssign+DivAssign{
    fn modulus()->u32;
    fn raw(val: u32)->Self;
    fn val(self)->u32;
    fn inv(self)->Self;
    #[inline]
    fn new<T: RemEuclidU32>(val: T)->Self{
        Self::raw(val.rem_euclid_u32(Self::modulus()))
    }
    #[inline]
    fn pow(self, mut n: u64)->Self{
        let mut x = self; let mut r = Self::raw(1);
        while n > 0{
            if n&1 == 1{
                r *= x;
            }
            x *= x; n >>= 1;
        }
        r
    }
}

pub trait RemEuclidU32{
    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);

trait InternalImplementations: ModIntBase{
    #[inline]
    fn inv_for_non_prime_modulus(this: Self)->Self{
        let (g, x) = inv_gcd(this.val().into(), Self::modulus().into());
        if g != 1{
            panic!("the inverse does not exist");
        }
        Self::new(x)
    }

    #[inline]
    fn default_impl()->Self{
        Self::raw(0)
    }

    #[inline]
    fn from_str_impl(s: &str) -> Result<Self, Infallible>{
        Ok(s.parse::<i64>().map(Self::new).unwrap_or_else(|_|
        todo!("parsing as an arbitrary precision integer?")))
    }

    #[inline]
    fn hash_impl(this: &Self, state: &mut impl Hasher){
        this.val().hash(state)
    }

    #[inline]
    fn display_impl(this: &Self, f: &mut Formatter<'_>)->fmt::Result{
        Display::fmt(&this.val(), f)
    }

    #[inline]
    fn debug_impl(this: &Self, f: &mut Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&this.val(), f)
    }

    #[inline]
    fn neg_impl(this: Self) -> Self{
        Self::sub_impl(Self::raw(0), this)
    }

    #[inline]
    fn add_impl(lhs: Self, rhs: Self)->Self{
        let modulus = Self::modulus();
        let mut val = lhs.val()+rhs.val();
        if val >= modulus{
            val -= modulus;
        }
        Self::raw(val)
    }

    fn sub_impl(lhs: Self, rhs: Self)->Self{
        let modulus = Self::modulus();
        let mut v = lhs.val().wrapping_sub(rhs.val());
        if v >= modulus{
            v = v.wrapping_add(modulus);
        }
        Self::raw(v)
    }

    fn mul_impl(lhs: Self, rhs: Self) -> Self;
    #[inline]
    fn div_impl(lhs: Self, rhs: Self)->Self{
        Self::mul_impl(lhs, rhs.inv())
    }
}

impl<M: Modulus> InternalImplementations for StaticModInt<M>{
    #[inline]
    fn mul_impl(lhs: Self, rhs: Self) -> Self {
        Self::raw((u64::from(lhs.val())*u64::from(rhs.val())%u64::from(M::VALUE))as u32)
    }
}

impl <I: Id> InternalImplementations for DynamicModInt<I>{
    #[inline]
    fn mul_impl(lhs: Self, rhs: Self) -> Self {
        Self::raw(I::companion_barrett().mul(lhs.val, rhs.val))
    }
}

macro_rules! impl_basic_traits {
    () => {};
    (impl <$generic_param:ident : $generic_param_bound:tt> _ for $self:ty; $($rest:tt)*) => {
        impl <$generic_param: $generic_param_bound> Default for $self {
            #[inline]
            fn default() -> Self {
                Self::default_impl()
            }
        }

        impl <$generic_param: $generic_param_bound> FromStr for $self {
            type Err = Infallible;

            #[inline]
            fn from_str(s: &str) -> Result<Self, Infallible> {
                Self::from_str_impl(s)
            }
        }

        impl<$generic_param: $generic_param_bound, V: RemEuclidU32> From<V> for $self {
            #[inline]
            fn from(from: V) -> Self {
                Self::new(from)
            }
        }

        #[allow(clippy::derive_hash_xor_eq)]
        impl<$generic_param: $generic_param_bound> Hash for $self {
            #[inline]
            fn hash<H: Hasher>(&self, state: &mut H) {
                Self::hash_impl(self, state)
            }
        }

        impl<$generic_param: $generic_param_bound> fmt::Display for $self {
            #[inline]
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                Self::display_impl(self, f)
            }
        }

        impl<$generic_param: $generic_param_bound> fmt::Debug for $self {
            #[inline]
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                Self::debug_impl(self, f)
            }
        }

        impl<$generic_param: $generic_param_bound> Neg for $self {
            type Output = $self;

            #[inline]
            fn neg(self) -> $self {
                Self::neg_impl(self)
            }
        }

        impl<$generic_param: $generic_param_bound> Neg for &'_ $self {
            type Output = $self;

            #[inline]
            fn neg(self) -> $self {
                <$self>::neg_impl(*self)
            }
        }

        impl_basic_traits!($($rest)*);
    };
}

impl_basic_traits! {
    impl <M: Modulus> _ for StaticModInt<M> ;
    impl <I: Id     > _ for DynamicModInt<I>;
}

macro_rules! impl_bin_ops {
    () => {};
    (for<$($generic_param:ident : $generic_param_bound:tt),*> <$lhs_ty:ty> ~ <$rhs_ty:ty> -> $output:ty { { $lhs_body:expr } ~ { $rhs_body:expr } } $($rest:tt)*) => {
        impl <$($generic_param: $generic_param_bound),*> Add<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn add(self, rhs: $rhs_ty) -> $output {
                <$output>::add_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Sub<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn sub(self, rhs: $rhs_ty) -> $output {
                <$output>::sub_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Mul<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn mul(self, rhs: $rhs_ty) -> $output {
                <$output>::mul_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Div<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn div(self, rhs: $rhs_ty) -> $output {
                <$output>::div_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl_bin_ops!($($rest)*);
    };
}

macro_rules! impl_assign_ops {
    () => {};
    (for<$($generic_param:ident : $generic_param_bound:tt),*> <$lhs_ty:ty> ~= <$rhs_ty:ty> { _ ~= { $rhs_body:expr } } $($rest:tt)*) => {
        impl <$($generic_param: $generic_param_bound),*> AddAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn add_assign(&mut self, rhs: $rhs_ty) {
                *self = *self + apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> SubAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn sub_assign(&mut self, rhs: $rhs_ty) {
                *self = *self - apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> MulAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn mul_assign(&mut self, rhs: $rhs_ty) {
                *self = *self * apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> DivAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn div_assign(&mut self, rhs: $rhs_ty) {
                *self = *self / apply($rhs_body, rhs);
            }
        }

        impl_assign_ops!($($rest)*);
    };
}

#[inline]
fn apply<F: FnOnce(X) -> O, X, O>(f: F, x: X) -> O {
    f(x)
}

impl_bin_ops! {
    for<M: Modulus> <StaticModInt<M>     > ~ <StaticModInt<M>     > -> StaticModInt<M>  { { |x| x  } ~ { |x| x  } }
    for<M: Modulus> <StaticModInt<M>     > ~ <&'_ StaticModInt<M> > -> StaticModInt<M>  { { |x| x  } ~ { |&x| x } }
    for<M: Modulus> <&'_ StaticModInt<M> > ~ <StaticModInt<M>     > -> StaticModInt<M>  { { |&x| x } ~ { |x| x  } }
    for<M: Modulus> <&'_ StaticModInt<M> > ~ <&'_ StaticModInt<M> > -> StaticModInt<M>  { { |&x| x } ~ { |&x| x } }
    for<I: Id     > <DynamicModInt<I>    > ~ <DynamicModInt<I>    > -> DynamicModInt<I> { { |x| x  } ~ { |x| x  } }
    for<I: Id     > <DynamicModInt<I>    > ~ <&'_ DynamicModInt<I>> -> DynamicModInt<I> { { |x| x  } ~ { |&x| x } }
    for<I: Id     > <&'_ DynamicModInt<I>> ~ <DynamicModInt<I>    > -> DynamicModInt<I> { { |&x| x } ~ { |x| x  } }
    for<I: Id     > <&'_ DynamicModInt<I>> ~ <&'_ DynamicModInt<I>> -> DynamicModInt<I> { { |&x| x } ~ { |&x| x } }

    for<M: Modulus, T: RemEuclidU32> <StaticModInt<M>     > ~ <T> -> StaticModInt<M>  { { |x| x  } ~ { StaticModInt::<M>::new } }
    for<I: Id     , T: RemEuclidU32> <DynamicModInt<I>    > ~ <T> -> DynamicModInt<I> { { |x| x  } ~ { DynamicModInt::<I>::new } }
}

impl_assign_ops! {
    for<M: Modulus> <StaticModInt<M> > ~= <StaticModInt<M>     > { _ ~= { |x| x  } }
    for<M: Modulus> <StaticModInt<M> > ~= <&'_ StaticModInt<M> > { _ ~= { |&x| x } }
    for<I: Id     > <DynamicModInt<I>> ~= <DynamicModInt<I>    > { _ ~= { |x| x  } }
    for<I: Id     > <DynamicModInt<I>> ~= <&'_ DynamicModInt<I>> { _ ~= { |&x| x } }

    for<M: Modulus, T: RemEuclidU32> <StaticModInt<M> > ~= <T> { _ ~= { StaticModInt::<M>::new } }
    for<I: Id,      T: RemEuclidU32> <DynamicModInt<I>> ~= <T> { _ ~= { DynamicModInt::<I>::new } }
}

macro_rules! impl_folding {
    () => {};
    (impl<$generic_param:ident : $generic_param_bound:tt> $trait:ident<_> for $self:ty { fn $method:ident(_) -> _ { _($unit:expr, $op:expr) } } $($rest:tt)*) => {
        impl<$generic_param: $generic_param_bound> $trait<Self> for $self {
            #[inline]
            fn $method<S>(iter: S) -> Self
            where
                S: Iterator<Item = Self>,
            {
                iter.fold($unit, $op)
            }
        }

        impl<'a, $generic_param: $generic_param_bound> $trait<&'a Self> for $self {
            #[inline]
            fn $method<S>(iter: S) -> Self
            where
                S: Iterator<Item = &'a Self>,
            {
                iter.fold($unit, $op)
            }
        }

        impl_folding!($($rest)*);
    };
}

impl_folding! {
    impl<M: Modulus> Sum<_>     for StaticModInt<M>  { fn sum(_)     -> _ { _(Self::raw(0), Add::add) } }
    impl<M: Modulus> Product<_> for StaticModInt<M>  { fn product(_) -> _ { _(Self::raw(1), Mul::mul) } }
    impl<I: Id     > Sum<_>     for DynamicModInt<I> { fn sum(_)     -> _ { _(Self::raw(0), Add::add) } }
    impl<I: Id     > Product<_> for DynamicModInt<I> { fn product(_) -> _ { _(Self::raw(1), Mul::mul) } }
}

macro_rules! modulus {
    ($($name: ident),*) => {
        $(
            #[derive(Copy, Clone, Eq, PartialEq)]
            enum $name{}
            impl Modulus for $name{
                const VALUE: u32 = $name as _;
                const HINT_VALUE_IS_PRIME: bool = true;
                fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>> {
                    thread_local! {
                        static BUTTERFLY_CACHE: RefCell<Option<ButterflyCache<$name>>> = Default::default();
                    }
                    &BUTTERFLY_CACHE
                }
            }
        )*
    };
}

pub fn convolution<M>(a: &[StaticModInt<M>], b: &[StaticModInt<M>])->Vec<StaticModInt<M>> where M: Modulus{
    if a.is_empty()||b.is_empty(){return vec![];}
    let (n, m) = (a.len(), b.len());
    if cmp::min(n, m) <= 60{
        let (n, m, a, b) = if n < m{(m, n, b, a)} else {(n, m, a, b)};
        let mut res = vec![StaticModInt::new(0); n+m-1];
        for i in 0..n{
            for j in 0..m{
                res[i+j] += a[i]*b[j];
            }
        }
        return res;
    }
    let (mut a, mut b) = (a.to_owned(), b.to_owned());
    let z = 1 << (32-((n+m-1)as u32).leading_zeros());
    a.resize(z, StaticModInt::raw(0));
    butterfly(&mut a);
    b.resize(z, StaticModInt::raw(0));
    butterfly(&mut b);
    for (a, b) in a.iter_mut().zip(&b){
        *a *= b;
    }
    butterfly_inv(&mut a);
    a.resize(n+m-1, StaticModInt::raw(0));
    let iz = StaticModInt::new(z).inv();
    for a in &mut a{
        *a *= iz;
    }
    a
}

fn butterfly<M: Modulus>(a: &mut [StaticModInt<M>]){
    let n = a.len();
    let h = 32-(n as u32).saturating_sub(1).leading_zeros();
    M::butterfly_cache().with(|cache|{
        let mut cache = cache.borrow_mut();
        let ButterflyCache{sum_e, ..} = cache.get_or_insert_with(prepare);
        for ph in 1..=h{
            let w = 1<<(ph-1);
            let p = 1<<(h-ph);
            let mut cur = StaticModInt::<M>::new(1);
            for s in 0..w{
                let offset = s << (h-ph+1);
                for i in 0..p{
                    let l = a[i+offset];
                    let r = a[i+offset+p]*cur;
                    a[i+offset] = l+r;
                    a[i+offset+p] = l-r;
                }
                cur *= sum_e[(!s).trailing_zeros()as usize];
            }
        }
    });
}

fn butterfly_inv<M: Modulus>(a: &mut [StaticModInt<M>]){
    let n = a.len(); let h = 32-(n as u32).saturating_sub(1).leading_zeros();
    M::butterfly_cache().with(|cache|{
        let mut cache = cache.borrow_mut();
        let ButterflyCache{sum_ie, ..} = cache.get_or_insert_with(prepare);
        for ph in (1..=h).rev(){
            let w = 1<<(ph-1);
            let p = 1<<(h-ph);
            let mut cur = StaticModInt::<M>::new(1);
            for s in 0..w{
                let offset = s << (h-ph+1);
                for i in 0..p{
                    let l = a[i+offset];
                    let r = a[i+offset+p];
                    a[i+offset] = l+r;
                    a[i+offset+p] = StaticModInt::new(M::VALUE+l.val()-r.val())*cur;
                }
                cur *= sum_ie[(!s).trailing_zeros()as usize];
            }
        }
    });
}

fn prepare<M: Modulus>() -> ButterflyCache<M>{
    let g = StaticModInt::<M>::raw(primitive_root(M::VALUE as i32)as u32);
    let mut es = [StaticModInt::<M>::raw(0); 30];
    let mut ies = [StaticModInt::<M>::raw(0); 30];
    let cnt2 = (M::VALUE-1).trailing_zeros() as usize;
    let mut e = g.pow(((M::VALUE-1)>>cnt2).into());
    let mut ie = e.inv();
    for i in (2..=cnt2).rev(){
        es[i-2] = e;
        ies[i-2] = ie;
        e *= e; ie *= ie;
    }
    let sum_e = es.iter().scan(StaticModInt::new(1), |acc, e|{
        *acc *= e; Some(*acc)
    }).collect();
    let sum_ie = ies.iter().scan(StaticModInt::new(1), |acc, ie|{
        *acc *= ie; Some(*acc)
    }).collect();
    ButterflyCache{sum_e, sum_ie}
}

pub fn convolution_raw<T, M>(a: &[T], b: &[T]) -> Vec<T> where T: RemEuclidU32+TryFrom<u32>+Clone,
                                                               T::Error: Debug, M: Modulus{
    let a = a.iter().cloned().map(Into::into).collect::<Vec<_>>();
    let b = b.iter().cloned().map(Into::into).collect::<Vec<_>>();
    convolution::<M>(&a, &b).into_iter().map(|z|{
        z.val.try_into().expect("ty < modulus")
    }).collect()
}

pub fn convolution_i64(a: &[i64], b: &[i64]) -> Vec<i64>{
    const M1: u64 = 754974721;
    const M2: u64 = 167772161;
    const M3: u64 = 469762049;
    const M2M3: u64 = M2*M3;
    const M3M1: u64 = M3*M1;
    const M1M2: u64 = M1*M2;
    const M1M2M3: u64 = M1M2.wrapping_mul(M3);
    modulus!(M1, M2, M3);
    if a.is_empty()||b.is_empty(){return vec![];}
    let (_, i1) = inv_gcd(M2M3 as _, M1 as _);
    let (_, i2) = inv_gcd(M3M1 as _, M2 as _);
    let (_, i3) = inv_gcd(M1M2 as _, M3 as _);
    let c1 = convolution_raw::<i64, M1>(a, b);
    let c2 = convolution_raw::<i64, M2>(a, b);
    let c3 = convolution_raw::<i64, M3>(a, b);
    c1.into_iter().zip(c2).zip(c3).map(|((c1, c2), c3)|{
        const OFFSET: &[u64] = &[0, 0, M1M2M3, 2*M1M2M3, 3*M1M2M3];
        let mut x = [(c1, i1, M1, M2M3), (c2, i2, M2, M3M1), (c3, i3, M3, M1M2)]
            .iter().map(|&(c, i, m1, m2)|
        c.wrapping_mul(i).rem_euclid(m1 as _).wrapping_mul(m2 as _)).fold(0, i64::wrapping_add);
        let mut diff = c1 - safe_mod(x, M1 as _);
        if diff < 0{
            diff += M1 as i64;
        }
        x = x.wrapping_sub(OFFSET[diff.rem_euclid(5)as usize]as _);
        x
    }).collect()
}

pub fn modulo(x: i128, y: i128)->i128{
    (x%y+y)%y
}

pub fn gcd(a: i128, b: i128)->i128{
    if b==0{
        a
    } else {
        gcd(b, modulo(a, b))
    }
}

pub fn ext_gcd(a: i128, b: i128)->(i128, i128, i128){
    if b==0{
        (a, 1, 0)
    } else {
        let (g, x, y) = ext_gcd(b, modulo(a, b));
        (g, y, x-a/b*y)
    }
}

pub fn crt(ss: &Vec<(i128, i128)>)->(i128, i128){
    let mut r = 0; let mut m = 1;
    for &(bi, mi) in ss{
        let (g, p, _) = ext_gcd(m, mi);
        if (bi-r)%g!=0{return (!0, !0);}
        let t = modulo(((bi - r) / g) * p, mi / g);
        r += m*t;
        m = m*mi/g;
        r = modulo(r, m);
    }
    (r, m)
}


pub fn convolution_nf(a: &[i64], b: &[i64], modulus: i64)->Vec<i64>{
    const M1: u64 = 754974721;
    const M2: u64 = 167772161;
    const M3: u64 = 469762049;
    match modulus{
        754974721 => {
            return convolution_raw::<i64, M1>(a, b);
        },
        167772161 => {
            return convolution_raw::<i64, M2>(a, b);
        },
        469762049 => {
            return convolution_raw::<i64, M3>(a, b);
        }
        _ => {}
    }
    const M1M2M3: i128 = M1 as i128*M2 as i128*M3 as i128;
    modulus!(M1, M2, M3);
    if a.is_empty()||b.is_empty(){return vec![];}
    let c1 = convolution_raw::<i64, M1>(a, b);
    let c2 = convolution_raw::<i64, M2>(a, b);
    let c3 = convolution_raw::<i64, M3>(a, b);
    c1.into_iter().zip(c2).zip(c3).map(|((c1, c2), c3)|{
        let (mut r, _) = crt(&vec![(c1 as i128, M1 as i128), (c2 as i128, M2 as i128), (c3 as i128, M3 as i128)]);
        let mut diff = (c1 as i128)-modulo(r, M1 as i128);
        if diff < 0{diff += M1 as i128}
        r -= match diff.rem_euclid(5){
            0 => {0},
            1 => {0},
            2 => {M1M2M3},
            3 => {2*M1M2M3},
            _ => {3*M1M2M3},
        };
        modulo(r, modulus as i128)as i64
    }).collect()
}

use proconio::fastout;
#[fastout]
fn main(){
    input!{
        n: usize, s: Usize1, t: Usize1,
        e: [(Usize1, Usize1); n-1],
    }
    let mut edge = vec![Vec::new(); n];
    let mut cnt = vec![0; n];
    for (i, &(u, v)) in e.iter().enumerate(){
        cnt[u] += 1; cnt[v] += 1;
        edge[u].push((v, i)); edge[v].push((u, i));
    }
    let mut way = Vec::new();
    let (u, v) = e[s];
    way.push(u);
    if !dfs(u, v, t, &edge, &mut way){
        way[0] = v;
        dfs(v, u, t, &edge, &mut way);
    }
    let mut f=vec![1; n+10];
    let mut z = 1i64;
    let mut inv = vec![1; n+10];
    for i in 2..n as i64+1{
        z=(z*i)%MOD;
        let w=(MOD-inv[(MOD%i)as usize]*(MOD/i)%MOD)%MOD;
        inv[i as usize] = w;
        f[i as usize] = z;
    }
    for i in 1..n{
        inv[i+1] = (inv[i+1]*inv[i])%MOD;
    }
    let mut heap = BinaryHeap::new();
    for &v in &way{
        let c = cnt[v]-2;
        let mut vc = vec![0];
        for i in 0..=c{
            vc.push(f[c]*inv[c-i]%MOD);
        }
        heap.push((Reverse(vc.len()), vc));
    }
    while heap.len() > 1{
        let (_, v1) = heap.pop().unwrap();
        let (_, v2) = heap.pop().unwrap();
        let nex = convolution_raw::<i64, Mod998244353>(&v1, &v2);
        heap.push((Reverse(nex.len()), nex));
    }
    let (_, res) = heap.pop().unwrap();
    let mut ans = vec![0; n];
    for (i, &x) in res.iter().enumerate(){
        ans[i] = x;
    }
    println!("{}", ans.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(" "));
}

fn dfs(p: usize, pre: usize, t: usize, edge: &Vec<Vec<(usize, usize)>>, way: &mut Vec<usize>)->bool{
    for &(nex, idx) in &edge[p]{
        if nex==pre{continue}
        way.push(nex);
        if idx==t{
            way.pop();
            return true;
        } else if dfs(nex, p, t, edge, way){
            return true;
        }
        way.pop();
    }
    false
}
0