#[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; pub type ModInt998244353 = StaticModInt; pub type ModInt = DynamicModInt; #[derive(Copy, Clone, Eq, PartialEq)] #[repr(transparent)] pub struct StaticModInt{ val: u32, phantom: PhantomDataM>, } impl StaticModInt{ #[inline(always)] pub fn modulus() -> u32{ M::VALUE } #[inline] pub fn new(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{ ::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 ModIntBase for StaticModInt{ #[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>>>; } #[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>>> { thread_local! { static BUTTERFLY_CACHE: RefCell>> = 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>>> { thread_local! { static BUTTERFLY_CACHE: RefCell>> = RefCell::default(); } &BUTTERFLY_CACHE } } pub struct ButterflyCache{ pub sum_e: Vec>, pub sum_ie: Vec>, } #[derive(Copy, Clone, Eq, PartialEq)] #[repr(transparent)] pub struct DynamicModInt{ val: u32, phantom: PhantomDataI>, } impl DynamicModInt{ #[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(val: T) -> Self { ::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 { ::pow(self, n) } #[inline] pub fn inv(self) -> Self{ Self::inv_for_non_prime_modulus(self) } } impl ModIntBase for DynamicModInt{ #[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+From+From+From+ From+From+From+From+From+From+From+ From+From+Copy+Eq+Hash+Display+Debug+Neg+Add+ Sub+Mul+Div+AddAssign+SubAssign+MulAssign+DivAssign{ fn modulus()->u32; fn raw(val: u32)->Self; fn val(self)->u32; fn inv(self)->Self; #[inline] fn new(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{ Ok(s.parse::().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 InternalImplementations for StaticModInt{ #[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 InternalImplementations for DynamicModInt{ #[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::from_str_impl(s) } } impl<$generic_param: $generic_param_bound, V: RemEuclidU32> From 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(&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 _ for StaticModInt ; impl _ for DynamicModInt; } 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 O, X, O>(f: F, x: X) -> O { f(x) } impl_bin_ops! { for > ~ > -> StaticModInt { { |x| x } ~ { |x| x } } for > ~ <&'_ StaticModInt > -> StaticModInt { { |x| x } ~ { |&x| x } } for <&'_ StaticModInt > ~ > -> StaticModInt { { |&x| x } ~ { |x| x } } for <&'_ StaticModInt > ~ <&'_ StaticModInt > -> StaticModInt { { |&x| x } ~ { |&x| x } } for > ~ > -> DynamicModInt { { |x| x } ~ { |x| x } } for > ~ <&'_ DynamicModInt> -> DynamicModInt { { |x| x } ~ { |&x| x } } for <&'_ DynamicModInt> ~ > -> DynamicModInt { { |&x| x } ~ { |x| x } } for <&'_ DynamicModInt> ~ <&'_ DynamicModInt> -> DynamicModInt { { |&x| x } ~ { |&x| x } } for > ~ -> StaticModInt { { |x| x } ~ { StaticModInt::::new } } for > ~ -> DynamicModInt { { |x| x } ~ { DynamicModInt::::new } } } impl_assign_ops! { for > ~= > { _ ~= { |x| x } } for > ~= <&'_ StaticModInt > { _ ~= { |&x| x } } for > ~= > { _ ~= { |x| x } } for > ~= <&'_ DynamicModInt> { _ ~= { |&x| x } } for > ~= { _ ~= { StaticModInt::::new } } for > ~= { _ ~= { DynamicModInt::::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 for $self { #[inline] fn $method(iter: S) -> Self where S: Iterator, { iter.fold($unit, $op) } } impl<'a, $generic_param: $generic_param_bound> $trait<&'a Self> for $self { #[inline] fn $method(iter: S) -> Self where S: Iterator, { iter.fold($unit, $op) } } impl_folding!($($rest)*); }; } impl_folding! { impl Sum<_> for StaticModInt { fn sum(_) -> _ { _(Self::raw(0), Add::add) } } impl Product<_> for StaticModInt { fn product(_) -> _ { _(Self::raw(1), Mul::mul) } } impl Sum<_> for DynamicModInt { fn sum(_) -> _ { _(Self::raw(0), Add::add) } } impl Product<_> for DynamicModInt { 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>>> { thread_local! { static BUTTERFLY_CACHE: RefCell>> = Default::default(); } &BUTTERFLY_CACHE } } )* }; } pub fn convolution(a: &[StaticModInt], b: &[StaticModInt])->Vec> 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(a: &mut [StaticModInt]){ 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::::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(a: &mut [StaticModInt]){ 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::::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() -> ButterflyCache{ let g = StaticModInt::::raw(primitive_root(M::VALUE as i32)as u32); let mut es = [StaticModInt::::raw(0); 30]; let mut ies = [StaticModInt::::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(a: &[T], b: &[T]) -> Vec where T: RemEuclidU32+TryFrom+Clone, T::Error: Debug, M: Modulus{ let a = a.iter().cloned().map(Into::into).collect::>(); let b = b.iter().cloned().map(Into::into).collect::>(); convolution::(&a, &b).into_iter().map(|z|{ z.val.try_into().expect("ty < modulus") }).collect() } pub fn convolution_i64(a: &[i64], b: &[i64]) -> Vec{ 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::(a, b); let c2 = convolution_raw::(a, b); let c3 = convolution_raw::(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{ const M1: u64 = 754974721; const M2: u64 = 167772161; const M3: u64 = 469762049; match modulus{ 754974721 => { return convolution_raw::(a, b); }, 167772161 => { return convolution_raw::(a, b); }, 469762049 => { return convolution_raw::(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::(a, b); let c2 = convolution_raw::(a, b); let c3 = convolution_raw::(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::(&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::>().join(" ")); } fn dfs(p: usize, pre: usize, t: usize, edge: &Vec>, way: &mut Vec)->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 }