fn read() -> (usize, usize) { let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); let mut it = s.trim().split_whitespace(); let n = it.next().unwrap().parse::().unwrap(); let k = it.next().unwrap().parse::().unwrap(); (n, k) } fn solve(n: usize, k: usize) { const MOD: usize = 998_244_353; // dp[i][j] = (way, sum): 直前2項がi, j であるような方法の数、数列の和 let mut dp = vec![vec![(0, 0); k]; k]; for (i, dp) in dp.iter_mut().enumerate() { for (j, dp) in dp.iter_mut().enumerate() { if i != j { *dp = (1, i + j); } } } for _ in 2..n { let mut next = vec![vec![(0, 0); k + 1]; k]; for (i, dp) in dp.iter().enumerate() { for (j, &(way, sum)) in dp.iter().enumerate() { if i == j { continue; } if j < i { next[j][j + 1].0 += way; next[j][j + 1].1 += sum; next[j][i].0 += MOD - way; next[j][i].1 += MOD - sum; next[j][i + 1].0 += way; next[j][i + 1].1 += sum; } else { next[j][0].0 += way; next[j][0].1 += sum; next[j][i].0 += MOD - way; next[j][i].1 += MOD - sum; next[j][i + 1].0 += way; next[j][i + 1].1 += sum; next[j][j].0 += MOD - way; next[j][j].1 += MOD - sum; } } } next.iter_mut().flatten().for_each(|p| { p.0 %= MOD; p.1 %= MOD; }); for next in next.iter_mut() { for i in 1..=k { next[i].0 = (next[i - 1].0 + next[i].0) % MOD; next[i].1 = (next[i - 1].1 + next[i].1) % MOD; } next.pop(); for (i, po) in next.iter_mut().enumerate() { po.1 = (po.1 + i * po.0) % MOD; } } dp = next; } let (w, s) = dp .iter() .flatten() .fold((0, 0), |s, a| ((s.0 + a.0) % MOD, (s.1 + a.1) % MOD)); println!("{} {}", w, s); } fn main() { let (n, k) = read(); solve(n, k); }