Submission #25616347


Source Code Expand

//! # Bundled libraries
//!
//! - `ext_gcd 0.1.0 (git+https://github.com/ia7ck/rust-competitive-programming#b386c09337c49e3879ca0d599676e9d83609d32a)`       licensed under **missing** as `crate::__cargo_equip::crates::__ext_gcd_0_1_0`
//! - `mod_int 0.1.0 (git+https://github.com/ia7ck/rust-competitive-programming#b386c09337c49e3879ca0d599676e9d83609d32a)`       licensed under **missing** as `crate::__cargo_equip::crates::mod_int`
//! - `procon_reader 0.1.0 (git+https://github.com/ia7ck/rust-competitive-programming#b386c09337c49e3879ca0d599676e9d83609d32a)` licensed under **missing** as `crate::__cargo_equip::crates::procon_reader`

pub use __cargo_equip::prelude::*;

use std::collections::HashMap;

use mod_int::ModInt998244353;
use procon_reader::ProconReader;
type Mint = ModInt998244353;

fn solve(
    l: usize,
    r: usize,
    ok: &Vec<Vec<bool>>,
    cmb: &Vec<Vec<Mint>>,
    memo: &mut HashMap<(usize, usize), Mint>,
) -> Mint {
    if l == r {
        return Mint::new(1);
    }
    if let Some(&ans) = memo.get(&(l, r)) {
        return ans;
    }
    let mut ans = Mint::new(0);
    // make pair (l, i)
    for i in ((l + 1)..r).step_by(2) {
        if ok[l][i] {
            // [l+1, i), [i+1, r)
            let l_val = solve(l + 1, i, ok, cmb, memo);
            let r_val = solve(i + 1, r, ok, cmb, memo);
            ans += l_val * r_val * cmb[(r - l) / 2][(r - (i + 1)) / 2];
        }
    }
    memo.insert((l, r), ans);
    ans
}

fn main() {
    let stdin = std::io::stdin();
    let mut rd = ProconReader::new(stdin.lock());

    let n: usize = rd.get();
    let m: usize = rd.get();
    let mut ok = vec![vec![false; n * 2]; n * 2];
    for _ in 0..m {
        let a: usize = rd.get();
        let b: usize = rd.get();
        ok[a - 1][b - 1] = true;
        ok[b - 1][a - 1] = true;
    }

    let mut cmb = vec![vec![Mint::new(0); n + 1]; n + 1];
    cmb[0][0] = Mint::new(1);
    for i in 1..=n {
        cmb[i][0] = Mint::new(1);
        for j in 1..=i {
            cmb[i][j] = cmb[i - 1][j - 1] + cmb[i - 1][j];
        }
    }
    let mut memo = HashMap::new();
    let ans = solve(0, n * 2, &ok, &cmb, &mut memo);
    println!("{}", ans.val());
}

// The following code was expanded by `cargo-equip`.

#[rustfmt::skip]
#[allow(unused)]
mod __cargo_equip {
    pub(crate) mod crates {
        pub mod __ext_gcd_0_1_0 {#[allow(clippy::many_single_char_names)]pub fn ext_gcd(a:i64,b:i64)->(i64,i64,i64){if b==0{if a==0{(0,0,0)}else{(1,0,a)}}else{let(q,r)=(a/b,a%b);let(s,t,g)=ext_gcd(b,r);(t,s-q*t,g)}}}
        pub mod mod_int {use crate::__cargo_equip::preludes::mod_int::*;pub use crate::__cargo_equip::macros::mod_int::*;use std::convert::TryInto;use std::fmt::Debug;use std::marker::PhantomData;use std::ops::{Add,AddAssign,Div,DivAssign,Mul,MulAssign,Sub,SubAssign};use ext_gcd::ext_gcd;pub trait Modulo:Copy+Clone+Debug{const P:i64;}#[derive(Copy,Clone,Debug)]pub struct ModInt<M>(i64,PhantomData<M>);impl<M:Modulo>ModInt<M>{pub fn new(x:i64)->Self{if 0<=x&&x<M::P{Self::new_raw(x)}else{Self::new_raw(x.rem_euclid(M::P))}}fn new_raw(x:i64)->Self{debug_assert!(0<=x&&x<M::P);Self(x,PhantomData)}pub fn val(self)->i64{self.0}pub fn p()->i64{M::P}pub fn pow<T>(self,exp:T)->Self where T:TryInto<u64>,<T as TryInto<u64> >::Error:Debug,{let mut res=1;let mut base=self.0;let mut exp=exp.try_into().unwrap();while exp>0{if exp&1==1{res*=base;res%=M::P;}base*=base;base%=M::P;exp>>=1;}Self::new_raw(res)}pub fn inv(self)->Self{assert_ne!(self.0,0,"Don't divide by zero!");let(x,_,g)=ext_gcd(self.0,M::P);assert_eq!(g,1,"{} is not prime!",M::P);Self::new(x)}}impl<M:Modulo,T:Into<ModInt<M> > >AddAssign<T>for ModInt<M>{fn add_assign(&mut self,rhs:T){self.0+=rhs.into().0;debug_assert!(0<=self.0&&self.0<=(M::P-1)*2);if self.0>=M::P{self.0-=M::P;}}}impl<M:Modulo,T:Into<ModInt<M> > >Add<T>for ModInt<M>{type Output=ModInt<M>;fn add(self,rhs:T)->Self::Output{let mut result=self;result+=rhs.into();result}}impl<M:Modulo,T:Into<ModInt<M> > >SubAssign<T>for ModInt<M>{fn sub_assign(&mut self,rhs:T){self.0-=rhs.into().0;debug_assert!(-(M::P-1)<=self.0&&self.0<M::P);if self.0<0{self.0+=M::P;}}}impl<M:Modulo,T:Into<ModInt<M> > >Sub<T>for ModInt<M>{type Output=ModInt<M>;fn sub(self,rhs:T)->Self::Output{let mut result=self;result-=rhs.into();result}}impl<M:Modulo,T:Into<ModInt<M> > >MulAssign<T>for ModInt<M>{fn mul_assign(&mut self,rhs:T){self.0*=rhs.into().0;if self.0>=M::P{self.0%=M::P;}}}impl<M:Modulo,T:Into<ModInt<M> > >Mul<T>for ModInt<M>{type Output=ModInt<M>;fn mul(self,rhs:T)->Self::Output{let mut result=self;result*=rhs.into();result}}impl<M:Modulo,T:Into<ModInt<M> > >DivAssign<T>for ModInt<M>{fn div_assign(&mut self,rhs:T){*self*=rhs.into().inv();}}impl<M:Modulo,T:Into<ModInt<M> > >Div<T>for ModInt<M>{type Output=ModInt<M>;fn div(self,rhs:T)->Self::Output{let mut result=self;result/=rhs.into();result}}macro_rules!impl_from_int{($($t:ty),+)=>{$(impl<M:Modulo>From<$t>for ModInt<M>{fn from(x:$t)->Self{Self::new(x as i64)}})+};}impl_from_int!(i32,i64,u32);macro_rules!impl_from_large_int{($($t:ty),+)=>{$(impl<M:Modulo>From<$t>for ModInt<M>{fn from(x:$t)->Self{Self::new((x%(M::P as$t))as i64)}})+};}impl_from_large_int!(u64,usize);define_mod_int_p!(Mod1000000007,ModInt1000000007,1_000_000_000+7);define_mod_int_p!(Mod998244353,ModInt998244353,998_244_353);}
        pub mod procon_reader {use std::io::BufRead;use std::str::FromStr;pub struct ProconReader<R>{r:R,l:String,i:usize,}impl<R:BufRead>ProconReader<R>{pub fn new(reader:R)->Self{Self{r:reader,l:String::new(),i:0,}}pub fn get<T>(&mut self)->T where T:FromStr,<T as FromStr>::Err:std::fmt::Debug,{self.skip_blanks();assert!(self.i<self.l.len());assert_ne!(&self.l[self.i..=self.i]," ");let rest=&self.l[self.i..];let len=rest.find(' ').unwrap_or_else(| |rest.len());let val=rest[..len].parse().unwrap_or_else(|e|panic!("{:?}, attempt to read `{}`",e,rest));self.i+=len;val}fn skip_blanks(&mut self){loop{match self.l[self.i..].find(|ch|ch!=' '){Some(j)=>{self.i+=j;break;}None=>{let mut buf=String::new();let num_bytes=self.r.read_line(&mut buf).unwrap_or_else(|_|panic!("invalid UTF-8"));assert!(num_bytes>0,"reached EOF :(");self.l=buf.trim_end_matches('\n').trim_end_matches('\r').to_string();self.i=0;}}}}pub fn get_vec<T>(&mut self,n:usize)->Vec<T>where T:FromStr,<T as FromStr>::Err:std::fmt::Debug,{(0..n).map(|_|self.get()).collect()}pub fn get_chars(&mut self)->Vec<char>{self.get::<String>().chars().collect()}}}
    }

    pub(crate) mod macros {
        pub mod __ext_gcd_0_1_0 {}
        pub mod mod_int {pub use crate::__macro_def_mod_int_define_mod_int_p as define_mod_int_p;}
        pub mod procon_reader {}
    }

    pub(crate) mod prelude {pub use crate::__cargo_equip::crates::*;}

    mod preludes {
        pub mod __ext_gcd_0_1_0 {}
        pub mod mod_int {pub(in crate::__cargo_equip)use crate::__cargo_equip::crates::__ext_gcd_0_1_0 as ext_gcd;}
        pub mod procon_reader {}
    }
}

#[cfg_attr(any(), rustfmt::skip)]
const _: () = {
    #[macro_export] macro_rules! __macro_def_mod_int_define_mod_int_p(($mod:ident,$mod_int:ident,$p:expr)=>{#[derive(Clone,Copy,Debug)]pub struct$mod;impl Modulo for$mod{const P:i64=$p;}pub type$mod_int=ModInt<$mod>;};);
};

Submission Info

Submission Time
Task F - Make Pair
User ikd
Language Rust (1.42.0)
Score 500
Code Size 7300 Byte
Status AC
Exec Time 212 ms
Memory 5136 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 500 / 500
Status
AC × 3
AC × 28
Set Name Test Cases
Sample example_00.txt, example_01.txt, example_02.txt
All example_00.txt, example_01.txt, example_02.txt, hand_00.txt, hand_01.txt, hand_02.txt, hand_03.txt, hand_04.txt, hand_05.txt, hand_06.txt, random_00.txt, random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt
Case Name Status Exec Time Memory
example_00.txt AC 6 ms 2060 KiB
example_01.txt AC 1 ms 2132 KiB
example_02.txt AC 2 ms 2080 KiB
hand_00.txt AC 212 ms 5004 KiB
hand_01.txt AC 205 ms 5112 KiB
hand_02.txt AC 2 ms 2460 KiB
hand_03.txt AC 2 ms 2504 KiB
hand_04.txt AC 2 ms 2476 KiB
hand_05.txt AC 2 ms 2132 KiB
hand_06.txt AC 1 ms 2164 KiB
random_00.txt AC 2 ms 2552 KiB
random_01.txt AC 2 ms 2608 KiB
random_02.txt AC 2 ms 2648 KiB
random_03.txt AC 179 ms 5084 KiB
random_04.txt AC 173 ms 5000 KiB
random_05.txt AC 4 ms 2244 KiB
random_06.txt AC 145 ms 5076 KiB
random_07.txt AC 156 ms 5052 KiB
random_08.txt AC 172 ms 5112 KiB
random_09.txt AC 106 ms 5040 KiB
random_10.txt AC 3 ms 2236 KiB
random_11.txt AC 109 ms 4936 KiB
random_12.txt AC 71 ms 4992 KiB
random_13.txt AC 77 ms 5040 KiB
random_14.txt AC 74 ms 5016 KiB
random_15.txt AC 2 ms 2044 KiB
random_16.txt AC 36 ms 5136 KiB
random_17.txt AC 31 ms 3872 KiB