結果
| 問題 |
No.3315 FPS Game
|
| コンテスト | |
| ユーザー |
👑 |
| 提出日時 | 2025-03-02 04:45:02 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 30,563 bytes |
| コンパイル時間 | 15,126 ms |
| コンパイル使用メモリ | 379,652 KB |
| 実行使用メモリ | 27,392 KB |
| 最終ジャッジ日時 | 2025-05-02 20:02:10 |
| 合計ジャッジ時間 | 18,645 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 7 TLE * 1 -- * 17 |
ソースコード
#[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()
}
#[inline(always)]
pub fn modulo(x: i128, y: i128)->i128{
(x%y+y)%y
}
#[inline(always)]
pub fn gcd(a: i128, b: i128)->i128{
if b==0{
a
} else {
gcd(b, modulo(a, b))
}
}
#[inline(always)]
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)
}
}
#[inline(always)]
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 res = vec![1];
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);
}
res = convolution_nf(&res, &vc, 998244353);
}
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
}