#![allow(dead_code, unused_imports)]

use std::fmt::Debug;
use std::str::FromStr;

fn read_stdin() -> String {
    let mut s = String::new();
    std::io::stdin()
        .read_line(&mut s)
        .expect("cannot read stdin");
    s.trim().to_string()
}

fn read<T>() -> T
where
    T: FromStr,
    <T as FromStr>::Err: Debug,
{
    read_stdin().parse::<T>().unwrap()
}

fn read_usize() -> usize {
    read::<usize>()
}

fn read_2<A, B>() -> (A, B)
where
    A: FromStr,
    <A as FromStr>::Err: Debug,
    B: FromStr,
    <B as FromStr>::Err: Debug,
{
    let s = read_stdin();
    let mut s = s.split_whitespace();
    let a = s.next().unwrap().parse::<A>().unwrap();
    let b = s.next().unwrap().parse::<B>().unwrap();
    (a, b)
}

fn read_3<A, B, C>() -> (A, B, C)
where
    A: FromStr,
    <A as FromStr>::Err: Debug,
    B: FromStr,
    <B as FromStr>::Err: Debug,
    C: FromStr,
    <C as FromStr>::Err: Debug,
{
    let s = read_stdin();
    let mut s = s.split_whitespace();
    let a = s.next().unwrap().parse::<A>().unwrap();
    let b = s.next().unwrap().parse::<B>().unwrap();
    let c = s.next().unwrap().parse::<C>().unwrap();
    (a, b, c)
}

fn read_4<A, B, C, D>() -> (A, B, C, D)
where
    A: FromStr,
    <A as FromStr>::Err: Debug,
    B: FromStr,
    <B as FromStr>::Err: Debug,
    C: FromStr,
    <C as FromStr>::Err: Debug,
    D: FromStr,
    <D as FromStr>::Err: Debug,
{
    let s = read_stdin();
    let mut s = s.split_whitespace();
    let a = s.next().unwrap().parse::<A>().unwrap();
    let b = s.next().unwrap().parse::<B>().unwrap();
    let c = s.next().unwrap().parse::<C>().unwrap();
    let d = s.next().unwrap().parse::<D>().unwrap();
    (a, b, c, d)
}

fn read_multiple<T: FromStr>() -> Vec<T>
where
    <T as FromStr>::Err: Debug,
{
    read_stdin()
        .split_whitespace()
        .map(|x| x.parse::<T>().expect("cannot parse stdin"))
        .collect()
}

/// NOTE: sort iter beforehand if required
fn count<T>(iter: &mut impl Iterator<Item = T>) -> Vec<(T, usize)>
where
    T: std::cmp::Ord,
{
    let iter = iter.collect::<Vec<_>>();
    //iter.sort();
    let (mut v, o, c) =
        iter.into_iter()
            .fold((Vec::new(), None, 0), |(mut v, last, count), item| {
                if let Some(o) = last {
                    if item == o {
                        (v, Some(o), count + 1)
                    } else {
                        v.push((o, count));
                        (v, Some(item), 1)
                    }
                } else {
                    (v, Some(item), 1)
                }
            });
    if let Some(i) = o {
        v.push((i, c));
    }
    v
}

fn max_subarray(v: impl Iterator<Item = i64>) -> (i64, (usize, usize)) {
    //assert!(v.len() > 0);
    let mut best_sum = 0;
    let (mut best_start, mut best_end) = (0, 0);
    let mut current_sum = 0;
    let mut current_start = 0;
    for (end, val) in v.enumerate() {
        if current_sum <= 0 {
            current_start = end;
            current_sum = val;
        } else {
            current_sum += val;
        }
        if current_sum > best_sum {
            best_sum = current_sum;
            best_start = current_start;
            best_end = end + 1;
        }
    }
    (best_sum, (best_start, best_end))
}

fn gcd(a: u64, b: u64) -> u64 {
    let mut a = a;
    let mut b = b;
    while a != b {
        if a > b {
            a = a - b
        } else {
            b = b - a
        }
    }
    a
}

fn factorize(mut n: u64) -> Vec<u64> {
    if n <= 3 {
        return vec![n];
    }
    let mut v = Vec::new();
    while n % 2 == 0 {
        n /= 2;
        v.push(2);
    }
    while n % 3 == 0 {
        n /= 3;
        v.push(3);
    }
    let mut f = 6;
    while (f - 1) * (f - 1) <= n {
        while n % (f - 1) == 0 {
            n /= f - 1;
            v.push(f - 1);
        }
        while n % (f + 1) == 0 {
            n /= f + 1;
            v.push(f + 1);
        }
        f += 6;
    }
    if n > 1 {
        v.push(n);
    }
    v
}

fn compact_factors(n: u64) -> Vec<(u64, usize)> {
    count(&mut factorize(n).into_iter())
}

fn all_factors(n: u64) -> Vec<u64> {
    let factors = compact_factors(n);
    let mut v = vec![1];
    for (fac, num) in factors {
        let ori = v.clone();
        for i in 1..num + 1 {
            v.append(
                &mut ori
                    .clone()
                    .into_iter()
                    .map(|f| f * fac.pow(i as u32))
                    .collect::<Vec<_>>(),
            )
        }
    }
    v.sort();
    v
}

use std::cmp::{max, min};
use std::collections::VecDeque;

fn first_factor(n: u32) -> u32 {
    if n % 2 == 0 {
        return 2;
    }
    if n % 3 == 0 {
        return 3;
    }
    let mut f = 6;
    while (f - 1) * (f - 1) <= n {
        if n % (f - 1) == 0 {
            return f - 1;
        }
        if n % (f + 1) == 0 {
            return f + 1;
        }
        f += 6;
    }
    return n;
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    for _ in 0..read_usize() {
        let n = read::<u32>();
        let f = first_factor(n);
        let a = n / f;
        println!("{} {}", a, n - a);
    }
    Ok(())
}


/// https://github.com/akiradeveloper/rust-comp-snippets

#[allow(unused_imports)]
use std::cmp::{max, min, Ordering};
#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
#[allow(unused_imports)]
use std::iter::FromIterator;

#[macro_export]
macro_rules! chmax {
    ($x:expr, $($v:expr),+) => {
        $(
            $x = std::cmp::max($x,$v);
        )+
    };
}

#[macro_export]
macro_rules! chmin {
    ($x:expr, $($v:expr),+) => {
        $(
            $x = std::cmp::min($x,$v);
        )+
    };
}

#[macro_export]
macro_rules! max {
    ($x:expr) => ( $x );
    ($x:expr, $($xs:expr),+) => {
        std::cmp::max($x, max!( $($xs),+ ))
    };
}

#[macro_export]
macro_rules! min {
    ($x:expr) => ( $x );
    ($x:expr, $($xs:expr),+) => {
        std::cmp::min($x, min!( $($xs),+ ))
    };
}

#[macro_export]
macro_rules! dvec {
    ($t:expr ; $len:expr) => {
        vec![$t; $len]
    };

    ($t:expr ; $len:expr, $($rest:expr),*) => {
        vec![dvec!($t; $($rest),*); $len]
    };
}

#[macro_export]
macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($($init: stmt),+; ; $($rest: tt)*) => {
        // avoid the `while true` lint
        cfor!($($init),+; !false; $($rest)*)
    };

    // for ($init; $cond; ) { ... }
    ($($init: stmt),+; $cond: expr; ; $body: block) => {
        cfor!{$($init),+; $cond; (); $body}
    };

    // for ($init; $cond; $step) { $body }
    ($($init: stmt),+; $cond: expr; $($step: expr),+; $body: block) => {
        {
            $($init;)+
            while $cond {
                let mut _first = true;
                let mut _continue = false;
                // this loop runs once, allowing us to use `break` and
                // `continue` as `goto` to skip forward to the
                // condition.
                //
                // the booleans above are very transparent to the
                // optimiser, since they are modified exactly once,
                // with nice control flow, and this this optimises to
                // be similar to C for loop.
                loop {
                    // if we *don't* hit this, there was a `break` in
                    // the body (otherwise the loop fell-through or
                    // was `continue`d.)
                    if !_first { _continue = true; break }
                    _first = false;

                    $body
                }
                if !_continue {
                    // the `if` wasn't hit, so we should propagate the
                    // `break`.
                    break
                }

                $($step;)+
            }
        }
    };
}

/// main

#[allow(unused_imports)]
use std::io::{stdin, stdout, BufWriter, Write};

// ref: tanakh <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
// diff: using Parser
#[macro_export]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut parser = Parser::from_str($s);
        input_inner!{parser, $($r)*}
    };
    (parser = $parser:ident, $($r:tt)*) => {
        input_inner!{$parser, $($r)*}
    };
    (new_stdin_parser = $parser:ident, $($r:tt)*) => {
        let stdin = std::io::stdin();
        let reader = std::io::BufReader::new(stdin.lock());
        let mut $parser = Parser::new(reader);
        input_inner!{$parser, $($r)*}
    };
    ($($r:tt)*) => {
        input!{new_stdin_parser = parser, $($r)*}
    };
}

#[macro_export]
macro_rules! input_inner {
    ($parser:ident) => {};
    ($parser:ident, ) => {};
    ($parser:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($parser, $t);
        input_inner!{$parser $($r)*}
    };
}

#[macro_export]
macro_rules! read_value {
    ($parser:ident, ( $($t:tt),* )) => {
        ( $(read_value!($parser, $t)),* )
    };
    ($parser:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($parser, $t)).collect::<Vec<_>>()
    };
    ($parser:ident, chars) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()
    };
    ($parser:ident, usize1) => {
        read_value!($parser, usize) - 1
    };
    ($parser:ident, $t:ty) => {
        $parser.next::<$t>().expect("Parse error")
    };
}

use std::io::BufRead;
use std::io;
use std::str;

// ref: tatsuya6502 <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e>
// ref: wariuni <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e#comment-7040a5ae96305e884eb9>
// diff: using std::io::BufRead::fill_buf()
pub struct Parser<R> {
    reader: R,
    buf: Vec<u8>,
    pos: usize,
}

impl Parser<io::Empty> {
    pub fn from_str(s: &str) -> Parser<io::Empty> {
        Parser {
            reader: io::empty(),
            buf: s.as_bytes().to_vec(),
            pos: 0,
        }
    }
}

impl<R:BufRead> Parser<R> {
    pub fn new(reader: R) -> Parser<R> {
        Parser {
            reader: reader,
            buf: vec![],
            pos: 0,
        }
    }
    pub fn update_buf(&mut self) {
        self.buf.clear();
        self.pos = 0;
        loop {
            let (len,complete) = {
                let buf2 = self.reader.fill_buf().unwrap();
                self.buf.extend_from_slice(buf2);
                let len = buf2.len();
                // diff: care when there is no empty space or line at the end
                if len == 0 {
                     break;
                }
                (len, buf2[len-1] <= 0x20)
            };
            self.reader.consume(len);
            if complete {
                break;
            }
        }
    }
    pub fn next<T:str::FromStr>(&mut self) -> Result<T, T::Err> {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            let mut end = begin;
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return str::from_utf8(&self.buf[begin..end]).unwrap().parse::<T>();
            }
            else {
                self.update_buf();
            }
        }
    }
}

#[allow(unused_macros)]
macro_rules ! debug { ( $ ( $ a : expr ) ,* ) => { eprintln ! ( concat ! ( $ ( stringify ! ( $ a ) , " = {:?}, " ) ,* ) , $ ( $ a ) ,* ) ; } }
#[doc = " https://github.com/hatoo/competitive-rust-snippets"]
const BIG_STACK_SIZE: bool = true;
#[allow(dead_code)]
fn main() {
    use std::thread;
    if BIG_STACK_SIZE {
        thread::Builder::new()
            .stack_size(32 * 1024 * 1024)
            .name("solve".into())
            .spawn(solve)
            .unwrap()
            .join()
            .unwrap();
    } else {
        solve();
    }
}

fn solve() {
    let out = stdout();
    let mut out = BufWriter::new(out.lock());
    input!{
        n:i64,m:i64,
    }
    let mi = max(0, n-2*m);
    let fullconn = n*(n-1)/2;
    let ma = if m==0 {
        n
    } else {
        let mut i=1;
        loop {
            if i*(i-1)/2 >= m {
                break;
            }
            i += 1;
        }
        n-i
    };
    writeln!(out,"{} {}", mi,ma);
}


use std::cmp::max;
use std::io;
use std::str;

pub struct Scanner<R> {
    reader: R,
    buffer: Vec<String>,
}

impl<R: io::BufRead> Scanner<R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buffer: vec![],
        }
    }

    pub fn token<T: str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            self.reader.read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
    let n: i64 = scan.token();
    let m: i64 = scan.token();
    if m == 0 {
        writeln!(out, "{} {}", n, n).ok();
        return;
    }
    let min_ans = max(n - 2 * m, 0);
    let k = ((1.0 + ((1 + 8 * m) as f64).sqrt()) / 2.0).ceil() as i64;
    let max_ans = n - k;
    writeln!(out, "{} {}", min_ans, max_ans).ok();
}

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout.lock());
    solve(&mut scan, &mut out);
}


fn main(){
    let mut s=String::new();
    let input=std::io::stdin().read_line(&mut s)
        .expect("");
    let mut iter=s.split_whitespace();
    let n : i64 =match iter.next(){
        Some(x) => x.trim().parse().expect(""),
        None => return ,
    };
    let m : i64 =match iter.next(){
        Some(x) => x.trim().parse().expect(""),
        None => return ,
    };

    let ans_min = if n-2*m>=0 {n-2*m} else {0};
    let mut ans_max = 0;

    for i in 0..n {
        if(i*(i-1)/2 >= m){
            ans_max=n-i;
            break;
        }
    }

    println!("{} {}",ans_min,ans_max);
}


#![allow(dead_code, unused_imports)]

use std::fmt::Debug;
use std::str::FromStr;

fn read_stdin() -> String {
    let mut s = String::new();
    std::io::stdin()
        .read_line(&mut s)
        .expect("cannot read stdin");
    s.trim().to_string()
}

fn read<T>() -> T
where
    T: FromStr,
    <T as FromStr>::Err: Debug,
{
    read_stdin().parse::<T>().unwrap()
}

fn read_usize() -> usize {
    read::<usize>()
}

fn read_2<A, B>() -> (A, B)
where
    A: FromStr,
    <A as FromStr>::Err: Debug,
    B: FromStr,
    <B as FromStr>::Err: Debug,
{
    let s = read_stdin();
    let mut s = s.split_whitespace();
    let a = s.next().unwrap().parse::<A>().unwrap();
    let b = s.next().unwrap().parse::<B>().unwrap();
    (a, b)
}

fn read_3<A, B, C>() -> (A, B, C)
where
    A: FromStr,
    <A as FromStr>::Err: Debug,
    B: FromStr,
    <B as FromStr>::Err: Debug,
    C: FromStr,
    <C as FromStr>::Err: Debug,
{
    let s = read_stdin();
    let mut s = s.split_whitespace();
    let a = s.next().unwrap().parse::<A>().unwrap();
    let b = s.next().unwrap().parse::<B>().unwrap();
    let c = s.next().unwrap().parse::<C>().unwrap();
    (a, b, c)
}

fn read_4<A, B, C, D>() -> (A, B, C, D)
where
    A: FromStr,
    <A as FromStr>::Err: Debug,
    B: FromStr,
    <B as FromStr>::Err: Debug,
    C: FromStr,
    <C as FromStr>::Err: Debug,
    D: FromStr,
    <D as FromStr>::Err: Debug,
{
    let s = read_stdin();
    let mut s = s.split_whitespace();
    let a = s.next().unwrap().parse::<A>().unwrap();
    let b = s.next().unwrap().parse::<B>().unwrap();
    let c = s.next().unwrap().parse::<C>().unwrap();
    let d = s.next().unwrap().parse::<D>().unwrap();
    (a, b, c, d)
}

fn read_multiple<T: FromStr>() -> Vec<T>
where
    <T as FromStr>::Err: Debug,
{
    read_stdin()
        .split_whitespace()
        .map(|x| x.parse::<T>().expect("cannot parse stdin"))
        .collect()
}

/// NOTE: sort iter beforehand if required
fn count<T>(iter: &mut impl Iterator<Item = T>) -> Vec<(T, usize)>
where
    T: std::cmp::Ord,
{
    let iter = iter.collect::<Vec<_>>();
    //iter.sort();
    let (mut v, o, c) =
        iter.into_iter()
            .fold((Vec::new(), None, 0), |(mut v, last, count), item| {
                if let Some(o) = last {
                    if item == o {
                        (v, Some(o), count + 1)
                    } else {
                        v.push((o, count));
                        (v, Some(item), 1)
                    }
                } else {
                    (v, Some(item), 1)
                }
            });
    if let Some(i) = o {
        v.push((i, c));
    }
    v
}

fn partial_sum<T>(v: impl Iterator<Item = T>) -> impl Iterator<Item = T>
where
    T: Default + std::ops::Add<Output = T> + Copy,
{
    v.scan(T::default(), |state, x| {
        *state = *state + x;
        Some(*state)
    })
}

fn max_subarray(v: impl Iterator<Item = i64>) -> (i64, (usize, usize)) {
    //assert!(v.len() > 0);
    let mut best_sum = 0;
    let (mut best_start, mut best_end) = (0, 0);
    let mut current_sum = 0;
    let mut current_start = 0;
    for (end, val) in v.enumerate() {
        if current_sum <= 0 {
            current_start = end;
            current_sum = val;
        } else {
            current_sum += val;
        }
        if current_sum > best_sum {
            best_sum = current_sum;
            best_start = current_start;
            best_end = end + 1;
        }
    }
    (best_sum, (best_start, best_end))
}

fn gcd(mut a: u64, mut b: u64) -> u64 {
    while a != 0 {
        let old_m = a;
        a = b % a;
        b = old_m;
    }
    b
}

/// returns gcd, and pair (x, y), such that x * a + b * y == gcd
fn egcd(a: i64, b: i64) -> (i64, i64, i64) {
    if a == 0 {
        (b, 0, 1)
    } else {
        let (g, x, y) = egcd(b % a, a);
        (g, y - (b / a) * x, x)
    }
}

fn factorize(mut n: u64) -> Vec<u64> {
    if n <= 3 {
        return vec![n];
    }
    let mut v = Vec::new();
    while n % 2 == 0 {
        n /= 2;
        v.push(2);
    }
    while n % 3 == 0 {
        n /= 3;
        v.push(3);
    }
    let mut f = 6;
    while (f - 1) * (f - 1) <= n {
        while n % (f - 1) == 0 {
            n /= f - 1;
            v.push(f - 1);
        }
        while n % (f + 1) == 0 {
            n /= f + 1;
            v.push(f + 1);
        }
        f += 6;
    }
    if n > 1 {
        v.push(n);
    }
    v
}

fn compact_factors(n: u64) -> Vec<(u64, usize)> {
    count(&mut factorize(n).into_iter())
}

fn all_factors(n: u64) -> Vec<u64> {
    if n == 0 {
        return vec![0];
    } else if n == 1 {
        return vec![1];
    }
    let factors = compact_factors(n);
    let mut v = vec![1];
    for (fac, num) in factors {
        let ori = v.clone();
        for i in 1..num + 1 {
            v.append(
                &mut ori
                    .clone()
                    .into_iter()
                    .map(|f| f * fac.pow(i as u32))
                    .collect::<Vec<_>>(),
            )
        }
    }
    v.sort();
    v
}

fn abs_diff<T>(a: T, b: T) -> T
where
    T: PartialOrd + std::ops::Sub<Output = T>,
{
    if a > b {
        a - b
    } else {
        b - a
    }
}

struct Permutations<T> {
    inner: Vec<T>,
    state: Vec<usize>,
    i: usize,
    start: bool,
}

impl<T> Permutations<T> {
    fn new(inner: Vec<T>) -> Self {
        Self {
            state: vec![0; inner.len()],
            i: 0,
            start: true,
            inner,
        }
    }
}

/*impl<T, X> From<X> for Permutations<T>
where
    X: IntoIterator<Item = T>,
{
    fn from(f: X) -> Self {
        Self::new(f.into_iter().collect::<Vec<T>>())
    }
}*/

impl<T> Iterator for Permutations<T>
where
    T: Clone,
{
    type Item = Vec<T>;
    fn next(&mut self) -> Option<Self::Item> {
        if self.start {
            self.start = false;
            return Some(self.inner.clone());
        }
        while self.i < self.inner.len() {
            if self.state[self.i] < self.i {
                if self.i % 2 == 0 {
                    self.inner.swap(0, self.i)
                } else {
                    self.inner.swap(self.state[self.i], self.i)
                }
                self.state[self.i] += 1;
                self.i = 0;
                return Some(self.inner.clone());
            } else {
                self.state[self.i] = 0;
                self.i += 1;
            }
        }
        None
    }
}

use std::cmp::{max, min, Ord, Ordering};
use std::collections::{BinaryHeap, VecDeque};
use std::mem::swap;

#[derive(Clone)]
struct Graph {
    nodes: usize,
    edges: Vec<Vec<(usize, u64)>>,
}

impl Graph {
    fn new(n: usize) -> Self {
        Self {
            nodes: n,
            edges: vec![Vec::new(); n + 1],
        }
    }

    fn add_edge(&mut self, x: usize, y: usize, cost: u64) {
        self.edges[x].push((y, cost));
        self.edges[y].push((x, cost));
    }

    fn dijkstra(&mut self, start: usize, end: usize) -> u64 {
        let mut dist = vec![None; self.nodes + 1];
        let mut prev = vec![None; self.nodes + 1];
        dist[start] = Some(0);
        let mut queue = (1..=self.nodes).collect::<Vec<_>>();
        queue.sort_unstable_by_key(|node| dist[*node].unwrap_or(std::u64::MAX));
        queue.reverse();
        while let Some(next_node) = queue.pop() {
            if next_node == end {
                return dist[next_node].unwrap();
            }
            for (neighbour, cost) in self.edges[next_node].iter() {
                let alt = dist[next_node].unwrap() + cost;
                if dist[*neighbour].is_none() {
                    dist[*neighbour] = Some(alt);
                    prev[*neighbour] = Some(next_node);
                } else {
                    if alt < dist[*neighbour].unwrap() {
                        dist[*neighbour] = Some(alt);
                        prev[*neighbour] = Some(next_node);
                    }
                }
            }
            //println!("{:?} {:?}", dist, prev);
            queue.sort_unstable_by_key(|node| dist[*node].unwrap_or(std::u64::MAX));
            queue.reverse();
        }
        0
    }

    fn set_cost(&mut self, x: usize, y: usize, cost: u64) {
        for i in 0..self.edges[x].len() {
            if self.edges[x][i].0 == y {
                self.edges[x][i].1 = cost
            }
        }
        for i in 0..self.edges[y].len() {
            if self.edges[y][i].0 == x {
                self.edges[y][i].1 = cost
            }
        }
    }
}

const MODULO: u64 = 1_000_000_007;

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
struct BigPrimeRing {
    inner: u64,
}

impl<T> From<T> for BigPrimeRing
where
    T: Into<u64>,
{
    fn from(n: T) -> Self {
        Self {
            inner: n.into() % MODULO,
        }
    }
}

impl<T> std::ops::Add<T> for BigPrimeRing
where
    T: Into<Self>,
{
    type Output = BigPrimeRing;
    fn add(self, rhs: T) -> Self::Output {
        Self {
            inner: (self.inner + rhs.into().inner) % MODULO,
        }
    }
}

impl<T> std::ops::AddAssign<T> for BigPrimeRing
where
    T: Into<Self>,
{
    fn add_assign(&mut self, rhs: T) {
        self.inner += rhs.into().inner;
        self.inner %= MODULO;
    }
}

impl<T> std::ops::Sub<T> for BigPrimeRing
where
    T: Into<Self>,
{
    type Output = BigPrimeRing;
    fn sub(self, rhs: T) -> Self::Output {
        Self {
            inner: (self.inner + MODULO - rhs.into().inner) % MODULO,
        }
    }
}

impl<T> std::ops::SubAssign<T> for BigPrimeRing
where
    T: Into<Self>,
{
    fn sub_assign(&mut self, rhs: T) {
        self.inner += MODULO;
        self.inner -= rhs.into().inner;
        self.inner %= MODULO;
    }
}

impl<T> std::ops::Mul<T> for BigPrimeRing
where
    T: Into<Self>,
{
    type Output = BigPrimeRing;
    fn mul(self, rhs: T) -> Self::Output {
        Self {
            inner: (self.inner * rhs.into().inner) % MODULO,
        }
    }
}

impl<T> std::ops::MulAssign<T> for BigPrimeRing
where
    T: Into<Self>,
{
    fn mul_assign(&mut self, rhs: T) {
        self.inner *= rhs.into().inner;
        self.inner %= MODULO;
    }
}

impl BigPrimeRing {
    fn inverse(self) -> Self {
        if self.inner == 0 {
            return self;
        }
        let (_g, mut x, _y) = egcd(self.inner as i64, MODULO as i64);
        if x < 0 {
            x += MODULO as i64;
        }
        Self { inner: x as u64 }
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let (n, mut m) = read_2::<u64, u64>();
    let min_isolate = if m == 0 {
        n
    } else if m * 2 > n {
        0
    } else {
        n - m * 2
    };
    let mut max_isolate = n;
    for i in 1..=n {
        if m > 0 {
            m -= min(i - 1, m);
            max_isolate -= 1;
        } else {
            break;
        }
    }
    println!("{} {}", min_isolate, max_isolate);
    Ok(())
}


// Try Codeforces
// author: Leonardone @ NEETSDKASU

fn main() {
    let mut stdin = String::new();
    std::io::Read::read_to_string(
        &mut std::io::stdin(),
        &mut stdin).unwrap();
    let mut stdin = stdin.split_whitespace();
    let mut get = || stdin.next().unwrap();
    macro_rules! get {
        ($t:ty) => (get().parse::<$t>().unwrap());
        () => (get!(i64));
    }

    let n = get!();
    let m = get!();

    if m == 0 {
        println!("{} {}", n, n);
        return;
    }

    let min = if m >= (n + 1) / 2 { 0 } else { n - m * 2 };
    let mut max = 0;
    for i in 1..n+1 {
        let v = i * (i - 1) / 2;
        if v >= m {
            max = n - i;
            break;
        }
    }

    println!("{} {}", min, max);
}


#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(dead_code)]
#![allow(unused_labels)]

use std::cmp::*;
use std::collections::*;
use std::io::{Write, BufWriter};
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, [ $t:tt ]) => {{
        let len = read_value!($next, usize);
        (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    }};

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

use std::io::*;
use std::str::FromStr;
use std::char::*;
macro_rules! debug {($($a:expr),*) => {eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);}}

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

use std::f64;

fn min<T: PartialOrd>(a:T, b:T) -> T {
    if a < b { a }
    else { b }
}

fn max<T: PartialOrd>(a:T, b:T) -> T {
    if a < b { b }
    else { a }
}

const MAX:i64 = 1000000009;
const INF:i64 = std::i64::MAX;
const MOD:i64 = 1e9 as i64 + 7;

struct Graph {
    e: Vec<Vec<usize>>,
    v: Vec<usize>,
    u: Vec<usize>,
    f: Vec<bool>,
    c: i64,
    flag: bool,
    vc: Vec<i64>,
}

impl Graph {
    fn new(n:usize) -> Self {
        Graph {
            e: vec![vec![];n],
            v: vec![],
            u: vec![n;n],
            f: vec![false;n],
            c: 0,
            flag: true,
            vc: vec![0;n],
        }
    }

    fn dfs(&mut self, crt: usize) {
        self.f[crt] = true;
        self.c = self.e[crt].len() as i64;
        if self.c != 2 {
            self.flag = false;
        }

        for i in 0..self.e[crt].len() {
            let v = self.e[crt][i];
            if self.f[v] { continue; }
            self.dfs(v);
        }
    }
}

fn binary_search(d:i64) -> f64 {
    let mut left = 0.0;
    let mut right = d as f64;

    while (right-left).abs() > 1e-12 {
        let a = (right+left)/2.0;
        let b = d as f64 - a;
        //debug!(left,mid,right,s[mid]);
        if a*b >= d as f64 { left = a; }
        else { right = a; }
    }
    left
}

fn neighbors(tree: &BTreeSet<usize>, val: usize) -> (Option<&usize>, Option<&usize>) {
    use std::ops::Bound::*;

    let mut before = tree.range((Unbounded, Excluded(val)));
    let mut after = tree.range((Excluded(val), Unbounded));

    (before.next_back(), after.next())
}

fn main() {
    // In order to avoid potential stack overflow, spawn a new thread.
    let stack_size = 104_857_600; // 100 MB
    let thd = std::thread::Builder::new().stack_size(stack_size);
    thd.spawn(|| solve()).unwrap().join().unwrap();
}

const MAX_A:i64 = 1e16 as i64;

fn gcd(a:i64, b:i64) -> i64 {
    if b==0 {return a;}
    gcd(b, a%b)
}

struct BIT {
    n: usize,
    bit: Vec<i64>,
}

impl BIT {
    fn new(n:usize) -> BIT {
        BIT {
            n,
            bit: vec![0;n+1],
        }
    }

    fn add(&mut self, a:usize, w:i64) {
        let mut x = a;
        while x <= self.n {
            self.bit[x] += w;
            x += (x as i64 & -(x as i64)) as usize;
        }
    }

    fn sum(&self, a:usize) -> i64 {
        let mut ret = 0;
        let mut x = a as i64;
        while x > 0 {
            ret += self.bit[x as usize];
            x -= x & -x;
        }
        ret
    }
}

fn solve() {
    let out = std::io::stdout();
    let mut out = BufWriter::new(out.lock());
    macro_rules! puts {
        ($($format:tt)*) => (let _ = write!(out,$($format)*););
    }

    input! {
        n: i64,
        m: i64
    }

    let mn = max(0,n-2*m);
    let mut c = 0;
    for v in 1..n+1 {
        let u = v*(v-1)/2;
        //debug!(m,u);
        if m > u {
            c = v+1;
        }
    }
    //debug!(c);
    let mx = max(0, n-c);
    puts!("{} {}\n", mn, mx);

}

/*

*/


#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
use std::io::{Write, BufWriter};
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

fn solve() {
    let out = std::io::stdout();
    let mut out = BufWriter::new(out.lock());
    macro_rules! puts {
        ($format:expr) => (write!(out,$format).unwrap());
        ($format:expr, $($args:expr),+) => (write!(out,$format,$($args),*).unwrap())
    }
    input!{
        n: i64,
        m: i64,
    }
    let mut p = 0;
    for i in 0 .. n + 1 {
        if m <= i * (i - 1) / 2 {
            p = i;
            break;
        }
    }
    puts!("{} {}\n", max(0, n - 2 * m), n - p);
}

fn main() {
    // In order to avoid potential stack overflow, spawn a new thread.
    let stack_size = 104_857_600; // 100 MB
    let thd = std::thread::Builder::new().stack_size(stack_size);
    thd.spawn(|| solve()).unwrap().join().unwrap();
}


use std::io;

fn read_ints() -> Vec<i64> {
    let stdin = io::stdin();
    let mut buff = String::new();
    stdin.read_line(&mut buff);
    buff.split_whitespace().map(|s| s.parse::<i64>().unwrap()).collect()
}

fn main() {
    let n = read_ints()[0];
    for _ in 0..n {
        let mut r1 = read_ints();
        let mut r2 = read_ints();
        r1.append(&mut r2);
        println!("{}", match r1.iter().sum() {
            0 => 0,
            4 => 2,
            _ => 1,
        });
    }
}


#![allow(dead_code)]
#![allow(unused)]
#![allow(unused_imports)]

use std::cmp::{max, min, Reverse};
use std::collections::{HashMap, HashSet};
use std::io::{self, prelude::*};
use std::{str, vec};

fn solve<R: BufRead, W: Write>(scan: &mut Scanner<R>, w: &mut W) {
    let a = (0..4)
        .map(|_| scan.next())
        .filter(|x: &i32| *x == 1)
        .count();

    writeln!(
        w,
        "{}",
        match a {
            0 => 0,
            1..=3 => 1,
            _ => 2,
        }
    );
}

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout.lock());

    let t = scan.next();
    for i in 0..t {
        solve(&mut scan, &mut out);
    }
}

pub struct Scanner<R> {
    reader: R,
    buf_str: Vec<u8>,
    buf_iter: str::SplitAsciiWhitespace<'static>,
}

impl<R: io::BufRead> Scanner<R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buf_str: vec![],
            buf_iter: "".split_ascii_whitespace(),
        }
    }

    pub fn next<T: str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse");
            }
            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_ascii_whitespace())
            }
        }
    }
}


use std::io::{self, prelude::*};
use std::str;

// IO

struct CPReader<R> {
    read: R,
    buf: Vec<u8>,
    iter: str::SplitAsciiWhitespace<'static>,
}

impl<R: io::BufRead> CPReader<R> {
    fn new(read: R) -> Self {
        Self { read, buf: vec![], iter: "".split_ascii_whitespace() }
    }
    fn update(&mut self) {
        self.buf.clear();
        self.read.read_until(b'\n', &mut self.buf).unwrap();
        self.iter = unsafe {
            let slice = str::from_utf8_unchecked(& self.buf);
            std::mem::transmute(slice.split_ascii_whitespace())
        }
    }
    fn getstr(&mut self) -> & str {
        loop {
            if let Some(ret) = self.iter.next() {
                break ret;
            }
            self.update();
        }
    }
    fn get<T: str::FromStr>(&mut self) -> T {
        return self.getstr().parse().ok().unwrap();
    }
}

// Main

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut input = CPReader::new(stdin.lock());
    let mut output = io::BufWriter::new(stdout.lock());

    let t:usize = input.get();
    for _ in 0..t {
        //let n:usize = input.get();
        let mut ans:i64 = 0;
        for _ in 0..4 {
            ans += input.get::<i64>();
        }
        writeln!(output, "{}", if ans == 4 { 2 } else { if ans != 0 {1} else {0}}).unwrap();
    }
}


#![allow(dead_code)]

use std::io::{Write};

//region  I/O
mod io {
    use std::io::{BufWriter, stdin, Stdout, StdoutLock};
    use std::str::{FromStr, SplitWhitespace};
    pub type Output<'a> = BufWriter<StdoutLock<'a>>;

    pub fn read_from_stdin() -> String {
        use std::io::Read;
        let mut input = String::new();

        stdin()
            .read_to_string(&mut input)
            .expect("Error reading from stdin");
        input
            .trim()
            .to_string()
    }

    pub fn output(stdout: &Stdout) -> Output {
        BufWriter::new(stdout.lock())
    }

    pub struct Input<'a> {
        values: SplitWhitespace<'a>
    }

    impl <'a> Input<'a> {
        pub fn from(input: &'a str) -> Self {
            Self { values: input.split_whitespace() }
        }

        pub fn next<T>(&mut self) -> T where T: FromStr {
            self
                .values
                .next()
                .unwrap()
                .parse::<T>()
                .ok()
                .unwrap()
        }

        pub fn vec<T>(&mut self, n: usize) -> Vec<T> where T: FromStr {
            (0..n)
                .map(|_| self.next())
                .collect()
        }
    }
}
//endregion

fn main() {
    let stdin = io::read_from_stdin();
    let stdout = std::io::stdout();
    let mut input = io::Input::from(&stdin);
    let mut output = io::output(&stdout);
    let k: usize = input.next();

    for _ in 0..k {
        solve(&mut input, &mut output)
    }
}

fn solve(input: &mut io::Input, output: &mut io::Output) {
    let a11: i32 = input.next();
    let a12: i32 = input.next();
    let a21: i32 = input.next();
    let a22: i32 = input.next();
    let ans = match (a11, a12, a21, a22) {
        (1, 1, 1, 1) => 2,
        (0, 0, 0, 0) => 0,
        _            => 1
    };

    writeln!(output, "{ans}").unwrap()
}


use std::fmt::Debug;
use std::io::stdin;
use std::ops::{Deref, Rem};
use std::str::FromStr;

fn solve() {
    let ones = gets()
        .split_whitespace()
        .map(|s| s.to_i() > 0)
        .chain(gets().split_whitespace().map(|s| s.to_i() > 0))
        .filter(|&x| x)
        .count();

    println!(
        "{}",
        match ones {
            0 => 0,
            1..=3 => 1,
            4 => 2,
            _ => panic!(),
        }
    );
}

fn main() {
    let t = gets().to_i();
    for _ in 0..t {
        solve();
    }
}

// ------- ✂ -------

fn gets() -> String {
    let mut line = String::new();
    stdin().read_line(&mut line).expect("Failed to read line");
    line.chomp()
}

trait StringExt {
    fn chomp(self) -> String;
}

impl StringExt for String {
    fn chomp(mut self) -> String {
        loop {
            match self.chars().last() {
                Some(c) if c.is_whitespace() => drop(self.pop()),
                _ => break,
            }
        }
        self
    }
}

trait StrExt {
    fn to_i(&self) -> i32;
    fn to_i64(&self) -> i64;
    fn to_f64(&self) -> f64;
    fn to_usize(&self) -> usize;

    fn parse_2<F>(&self) -> (F, F)
    where
        F: FromStr,
        <F as FromStr>::Err: Debug;
}

impl<T> StrExt for T
where
    T: Deref<Target = str>,
{
    fn to_i(&self) -> i32 {
        self.parse().unwrap()
    }
    fn to_i64(&self) -> i64 {
        self.parse().unwrap()
    }
    fn to_f64(&self) -> f64 {
        self.parse().unwrap()
    }
    fn to_usize(&self) -> usize {
        self.parse().unwrap()
    }

    fn parse_2<F>(&self) -> (F, F)
    where
        F: FromStr,
        <F as FromStr>::Err: Debug,
    {
        let mut it = self.split_whitespace();
        let fst: F = it.next().unwrap().parse().unwrap();
        let snd: F = it.next().unwrap().parse().unwrap();
        (fst, snd)
    }
}

trait IsOdd {
    fn is_odd(&self) -> bool;

    fn is_even(&self) -> bool {
        !self.is_odd()
    }
}

impl<T> IsOdd for T
where
    T: Copy + PartialEq + From<u8> + Rem<Output = T>,
{
    fn is_odd(&self) -> bool {
        *self % T::from(2) == T::from(1)
    }
}


#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(unused_must_use)]
use collections::*;
use std::io::Write;
use std::*;

fn test_case<W: Write>(sc: &mut input::In, out: &mut std::io::BufWriter<W>) {
    let (a,b,c,d):(usize, usize, usize, usize) = (sc.read(), sc.read(), sc.read(), sc.read());
    let e = a+b+c+d;
    if e==0{
        writeln!(out, "0");
    }else if e==4 {
        writeln!(out, "2");
    }else{
        writeln!(out, "1");
    }
}

fn main() {
    use std::io::Read;
    let mut s = String::new();
    std::io::stdin().read_to_string(&mut s).unwrap();
    let mut sc = input::In::new(&s);
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    let t = 1;
    let t: usize = sc.read();
    for _ in 0..t {
        test_case(&mut sc, &mut out);
    }
}

mod input {
    use std::str::FromStr;
    use std::str::SplitWhitespace;
    pub struct In<'a> {
        iter: SplitWhitespace<'a>,
    }
    impl<'a> In<'a> {
        pub fn new(s: &'a String) -> Self {
            Self {
                iter: s.split_whitespace(),
            }
        }
        pub fn read<T: FromStr>(&mut self) -> T {
            self.iter.next().unwrap().parse::<T>().ok().unwrap()
        }

        pub fn read_bytes(&mut self) -> Vec<u8> {
            self.iter.next().unwrap().bytes().collect()
        }
        pub fn read_chars(&mut self) -> Vec<char> {
            self.iter.next().unwrap().chars().collect()
        }
        pub fn read_vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.read()).collect()
        }
    }
}


use std::fmt::{Display};
use std::io::{stdout, stdin, Write, BufReader, BufWriter, BufRead, Stdin, Stdout};

fn main() -> () {
    let io = &mut IO::new();

    for _ in 0..io.read_i32() {
        let first_sum = io.read_array_i32(" ").iter().sum::<i32>();
        let second_sum = io.read_array_i32(" ").iter().sum::<i32>();

        io.write(match first_sum + second_sum {
            0 => 0,
            1..=3 => 1,
            _ => 2
        }, "\n");
    }

}

struct IO {
    reader: BufReader<Stdin>,
    writer: BufWriter<Stdout>,
}

impl Drop for IO {
    fn drop(&mut self) {
        self.flush();
    }
}

impl IO {
    pub fn new() -> IO {
        IO {
            reader: BufReader::new(stdin()),
            writer: BufWriter::new(stdout()),
        }
    }

    pub fn read_i32(&mut self) -> i32 {
        let mut res = String::new();
        self.reader.read_line(&mut res).expect("error read");
        return res.trim().parse().unwrap();
    }

    pub fn read_array_i32(&mut self, split: &str) -> Vec<i32> {
        let mut res = String::new();
        self.reader.read_line(&mut res).expect("error read");
        return res.trim().split(split).map(|x| x.parse().expect("not is i32")).collect::<Vec<i32>>();
    }

    pub fn read_array_i64(&mut self, split: &str) -> Vec<i64> {
        let mut res = String::new();
        self.reader.read_line(&mut res).expect("error read");
        return res.trim().split(split).map(|x| x.parse().expect("not is i64")).collect::<Vec<i64>>();
    }

    pub fn read_str(&mut self) -> String {
        let mut res = String::new();
        self.reader.read_line(&mut res).expect("error read");
        res
    }

    pub fn write<T: Display>(&mut self, value: T, end: &str) {
        self.writer.write(value.to_string().as_bytes()).expect("error write");
        self.writer.write(end.as_bytes()).expect("error write");
    }

    pub fn flush(&mut self) {
        self.writer.flush().expect("error flush");
    }
}


use std::io;

fn main() {
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer)
        .expect("Failed to read line");

    let num_letters = buffer.trim().parse::<i32>().expect("parse error");
    if num_letters == 0 {
        println!("0");
        return;
    }

    buffer.clear();
    io::stdin().read_line(&mut buffer)
        .expect("Failed to read line");
    let mut splitted: Vec<&str> = buffer.trim().split('W').collect();
    splitted.retain(|&i|i != "");
    println!("{}", splitted.len());

    for sub in &splitted {
        print!("{} ", sub.len());
    }
    println!();
}


fn main() {
    let mut input: String = String::new();
    std::io::stdin().read_line(&mut input).expect("INPUT::read line failed");
    let amount = input.trim().parse::<i32>().unwrap();

    input.clear();
    std::io::stdin().read_line(&mut input).expect("INPUT::read line failed");
    let vec:Vec<char> = input.trim().chars().collect::<Vec<char>>();
    let mut crossword: Vec<i32> = vec![];
    let mut max_len = i32::default();

    for _item in &vec {
        match _item {
            'B' => max_len += 1,
            'W' => {
                if max_len > 0 {
                    crossword.push(max_len);
                    max_len = 0;
                }
            },
            _ => println!("ERROR::letter not exist")
        }

    }

    if max_len > 0 {
        crossword.push(max_len);
        max_len = 0;
    }

    match crossword.len() {
        0 => println!("0"),
        _ => {
            println!("{}", crossword.len());
            for _item in &crossword {
                print!("{} ", _item);
            }
        }
    }

    //println!("{:?}", vec);
    //println!("{:?}", crossword);
}


#[allow(unused_imports)]
use std::cmp::{max,min};
#[allow(unused_imports)]
use std::collections::{HashMap,HashSet,VecDeque};

#[allow(unused_macros)]
macro_rules! readln {
    () => {{
        use std::io;

        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim().to_string()
    }};
    ( $t:ty ) => {{
        let input = readln!();
        input.parse::<$t>().unwrap()
    }};
    ( $( $t:ty ),+ ) => {{
        let input = readln!();
        let mut input = input.split_whitespace();
        (
            $(
                input.next().unwrap().parse::<$t>().unwrap(),
            )+
        )
    }}
}

#[allow(unused_macros)]
macro_rules! readvec {
    ( $t:ty ) => {{
        let input = readln!();
        let mut input = input.split_whitespace();
        let mut result = Vec::new();
        for elem in input {
            result.push(elem.parse::<$t>().unwrap());
        }
        result
    }}
}

fn main() {
    readln!();
    let s = readln!();
    let mut res : Vec<i32> = Vec::new();
    let mut i = 0;
    let n = s.len();
    let z = s.into_bytes();
    while i < n {
        if z[i] == 'W' as u8 {
            i+=1;
        } else {
            let st = i;
            while i < n && z[i] == 'B' as u8 {
                i+=1;
            }
            res.push((i-st) as i32);
        }
    }
    println!("{}",res.len());
    println!("{}",res.iter().map(|x|x.to_string()).collect::<Vec<String>>().join(" "));
}


//spnauti-rust
#[allow(unused_macros)]
macro_rules! a {
    ($c: tt, $x: expr, $y: expr) => {{
        let b = $y; let a = &mut $x;
        if b $c *a { *a = b; true } else { false }
    }};
}
use std::io::*;
use std::str::*;
use std::fmt::Debug;
struct WordReader<'a> { it : SplitAsciiWhitespace<'a>, }
#[allow(dead_code)]
impl<'a> WordReader<'a> {
    fn new<T: Read>(b: &mut String, mut r: T) -> WordReader {
        b.clear();
        r.read_to_string(b).unwrap();
        WordReader { it: b.split_ascii_whitespace() }
    }
    fn from_stdin(b: &mut String) -> WordReader {
        WordReader::new(b, stdin())
    }
    fn sl(&mut self) ->  &str { self.it.next().unwrap() }
    fn bs(&mut self) -> &[u8] { self.sl().as_bytes()    }
    fn s(&mut self) -> String { String::from(self.sl()) }
    fn i(&mut self) ->    i32 { self.p()                }
    fn u(&mut self) ->  usize { self.p()                }
    fn vi(&mut self, n: usize) -> Vec<i32> {
        self.vp::<i32>(n)
    }
    fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
        self.sl().parse::<T>().unwrap()
    }
    fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
        (0..n).map(|_| self.p()).collect()
    }
}

fn main() {
    let mut bin = String::new();
    let mut input = WordReader::from_stdin(&mut bin);

    input.i();
    let a = input.sl().split(|a| a == 'W').map(|a| a.len()).filter(|&a| a > 0).collect::<Vec<_>>();
    println!("{}", a.len());
    for x in a {
        print!("{} ", x);
    }
}


#![allow(unused_imports)]
use std::io::*;
use std::cmp::*;
use std::collections::*;

macro_rules! debug(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

struct Scanner {
   buffer : std::collections::VecDeque<String>
}

impl Scanner {

   fn new() -> Scanner {
      Scanner {
         buffer: std::collections::VecDeque::new()
      }
   }

   fn process(&mut self) -> String {
      if self.buffer.len() == 0 {
         let mut input = String::new();
         std::io::stdin().read_line(&mut input).ok();
         for word in input.split_whitespace() {
            self.buffer.push_back(word.to_string())
         }
      }

      self.buffer.pop_front().unwrap()
   }

   fn next<T : std::str::FromStr >(&mut self) -> T {
      self.process().parse::<T>().ok().unwrap()
   }

   fn next_char(&mut self) -> char {
      self.process().into_bytes()[0] as char
   }
}

fn main() {
   let mut sin = Scanner::new();
   let n : usize = sin.next();
   let x : String = sin.next();

   let mut count = 0;
   let mut counts : Vec<i32> = Vec::new();

   for i in x.chars()
   {
      if i == 'B' {
         count += 1;
      } else if i == 'W' && count != 0 {
         counts.push(count);
         count = 0;
      }
   }

   if count != 0 {
      counts.push(count);
   }

   println!("{}", counts.len());
   if counts.len() > 0 {
      print!("{}", counts[0]);
      for i in 1..counts.len() {
         print!(" {}", counts[i]);
      }
      println!("");
   }
}


struct Scan {
    buffer: std::collections::VecDeque<String>,
}

impl Scan {
    fn new() -> Scan {
        Scan {
            buffer: std::collections::VecDeque::new(),
        }
    }

    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop_front() {
                break token.parse::<T>().ok().unwrap();
            }
            let mut line = String::new();
            std::io::stdin().read_line(&mut line).expect("Fail to read");
            self.buffer = line.split_whitespace().map(String::from).collect();
        }
    }

    fn next_n<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.next::<T>()).collect()
    }
}

fn _main() {
    let mut scan = Scan::new();
    let _n: usize = scan.next();
    let input: Vec<char> = scan.next::<String>().chars().take(_n).collect();
    let mut results: Vec<usize> = vec![];
    let mut count: usize = 0;
    for &item in input.iter() {
        if item == 'B' {
            count += 1;
        }
        if item == 'W' {
            if count != 0 {
                results.push(count);
            }
            count = 0;
        }
    }
    if count != 0 {
        results.push(count);
    }
    println!("{}", results.len());
    for &item in results.iter() {
        print!("{} ", item);
    }
    println!();
}

fn main() {
    std::thread::Builder::new()
        .stack_size(1 << 23)
        .spawn(_main)
        .unwrap()
        .join()
        .unwrap();
}


#![allow(unused_imports)]
use std::collections::{HashSet, HashMap};
use std::cmp::{min,max};
use std::io;
use std::str;

struct Scanner<R> {
    reader: R,
    buf_str: Vec<u8>,
    buf_iter: str::SplitWhitespace<'static>,
}
impl<R: io::BufRead> Scanner<R> {
    fn new(reader: R) -> Self {
        Self { reader, buf_str: vec![], buf_iter: "".split_whitespace() }
    }
    fn token<T: str::FromStr>(&mut self) -> T {
        loop {
            // If we have another token in this line
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse"); // calls parse::<T>() on the current token and returns it.
            }

            // If we do not have another token in the line then
            // we should go to the next line.
            self.buf_str.clear(); // empty out the buffer that holds the current line
            self.reader.read_until(b'\n', &mut self.buf_str).expect("Failed read"); // read a new line into the buffer

            // create an iterator over the white space delimited strings of the current line
            self.buf_iter = unsafe {
                let slice = str::from_utf8_unchecked(&self.buf_str); // makes a string from utf8 characters in the current line
                std::mem::transmute(slice.split_whitespace()) // transmutes the memory in place
            }
        }
    }
}

fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
    let n = scan.token::<usize>();
    let mut s = vec![];
    for _ in 0..n {
        s.push(scan.token::<u8>());
    }
    let mut max: u8 = 0;

    for i in 0..n {
        for j in i..n {
            let mut curr = 0;
            for k in 0..n {
                curr += {
                    if k < i {s[k]}
                    else if k >= i && k <= j {1 - s[k]}
                    else {s[k]}
                }
            }
            max = u8::max(curr, max);
        }
    }
    writeln!(out, "{}", max);
}

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout.lock());
    solve(&mut scan, &mut out);
}


use std::cmp::max;
use std::io;
use std::io::Stdin;
use std::str::FromStr;

fn read_line(stdin : &Stdin, line : &mut String) {
    match stdin.read_line(line) {
        Ok(_) => return,
        Err(msg) => panic!("Could not read line! Message: {}.", msg),
    }
}

fn parse_t<T : FromStr>(s : &str) -> T {
    match s.trim().parse() {
        Ok(y) => y,
        Err(_) => panic!("Could not read from string!"),
    }
}

fn read_t<T : FromStr>(stdin : &Stdin) -> T {
    let mut line = String::new();
    read_line(stdin, &mut line);
    parse_t(&line)
}

fn read_ts<T : FromStr>(stdin : &Stdin, ts : &mut Vec<T>) {
    let mut line = String::new();
    read_line(stdin, &mut line);
    let word_iter = line.split_whitespace();
    for word in word_iter {
        let x = parse_t(word);
        ts.push(x);
    }
}

fn max_ones(xs : &Vec<i8>) -> i8 {
    let s = xs.iter().sum::<i8>();
    let mut ys = vec![];
    let one = 1;
    let minus_one = -1;
    for &x in xs.iter() {
        if x == 0 {
            ys.push(one);
        } else {
            ys.push(minus_one);
        }
    }
    let mut max_upto_i = ys[0];
    let mut max_ending_at_i = ys[0];
    for i in 1 .. ys.len() {
        let y = ys[i];
        max_ending_at_i = max(y, max_ending_at_i + y);
        max_upto_i = max(max_ending_at_i, max_upto_i);
    }
    s + max_upto_i
}

fn main() {
    let stdin = io::stdin();
    let _ : usize = read_t(&stdin);
    let mut xs = vec![];
    read_ts(&stdin, &mut xs);
    let result = max_ones(&xs);
    println!("{}", result);
}


// use rand::Rng;

use std::collections::*;
use std::io;

fn trim_newline(s: &mut String) {
    if s.ends_with('\n') {
        s.pop();
        if s.ends_with('\r') {
            s.pop();
        }
    }
}
macro_rules! parse_input {
    ($t:ident) => {{
        let mut input_line = String::new();
        io::stdin().read_line(&mut input_line).unwrap();
        trim_newline(&mut input_line);
        input_line.parse::<$t>().unwrap()
    }};
}

macro_rules! split_input {
    ($t:ident) => {{
        parse_input!(String)
            .split(" ")
            .map(|z| z.parse::<$t>().unwrap())
            .collect::<Vec<$t>>()
    }};
}

fn main() {
    let a = parse_input!(u64);
    let b = split_input!(u64);
    let mut best = 0;
    let mut cur = 0;
    let mut ones: u64 = b.iter().sum();
    if ones as usize == b.len() {
        ones -= 1;
    }
    for p in b.iter() {
        if *p == 0 {
            cur += 1;
            best = std::cmp::max(best, cur);
        } else if cur > 0 {
            cur -= 1;
        }
    }

    println!("{}", ones + best);
}


use std::cmp::max;
use std::io;
use std::io::Stdin;
use std::str::FromStr;

fn read_line(stdin : &Stdin, line : &mut String) {
    match stdin.read_line(line) {
        Ok(_) => return,
        Err(msg) => panic!("Could not read line! Message: {}.", msg),
    }
}

fn parse_t<T : FromStr>(s : &str) -> T {
    match s.trim().parse() {
        Ok(y) => y,
        Err(_) => panic!("Could not read from string!"),
    }
}

fn read_t<T : FromStr>(stdin : &Stdin) -> T {
    let mut line = String::new();
    read_line(stdin, &mut line);
    parse_t(&line)
}

fn read_ts<T : FromStr>(stdin : &Stdin, ts : &mut Vec<T>) {
    let mut line = String::new();
    read_line(stdin, &mut line);
    let word_iter = line.split_whitespace();
    for word in word_iter {
        let x = parse_t(word);
        ts.push(x);
    }
}

fn max_ones(ys : &Vec<i8>) -> i8 {
    let one = 1;
    let minus_one = -1;
    let mut s = ys[0];
    let y_0 = if ys[0] == 0 { one } else { minus_one };
    let mut max_upto_i = y_0;
    let mut max_ending_at_i = y_0;
    for i in 1 .. ys.len() {
        let ys_i = ys[i];
        s = s + ys_i;
        let y = if ys_i == 0 { one } else { minus_one };
        max_ending_at_i = max(y, max_ending_at_i + y);
        max_upto_i = max(max_ending_at_i, max_upto_i);
    }
    s + max_upto_i
}

fn main() {
    let stdin = io::stdin();
    let _ : usize = read_t(&stdin);
    let mut xs = vec![];
    read_ts(&stdin, &mut xs);
    let result = max_ones(&xs);
    println!("{}", result);
}


fn solve() {
    let n: usize = {
        let mut buf = String::new();
        std::io::stdin().read_line(&mut buf).unwrap();
        buf.trim_end().parse().unwrap()
    };

    let a: Vec<i32> = {
        let mut buf = String::new();
        std::io::stdin().read_line(&mut buf).unwrap();
        buf.split_whitespace().map(|s| s.parse().unwrap()).collect()
    };

    let mut ans = 0;
    for i in 0..n {
        for j in i..n {
            let mut tmp = a.clone();
            for k in i..j + 1 {
                tmp[k] = 1 - tmp[k];
            }
            ans = ans.max(tmp.iter().sum());
        }
    }

    println!("{}", ans);
}

fn main() {
    solve();
}


fn main() {
    inputv! {
        n:usize,
    }
    let a = input_vector::<usize>();
    let mut ans = 0;
    let one_count = a.iter().filter(|&&q| q == 1).count();
    for i in 0..n {
        for j in i + 1..=n {
            let zero = a[i..j].iter().filter(|&&q| q == 0).count();
            let one = j - i - zero;
            ans = std::cmp::max(ans, one_count + zero - one);
        }
    }
    println!("{}", ans);
}

//https://github.com/manta1130/competitive-template-rs

use input::*;

pub mod input {
    use std::cell::RefCell;
    use std::io;
    pub const SPLIT_DELIMITER: char = ' ';
    pub use std::io::prelude::*;

    #[macro_export]
    thread_local! {
        pub static INPUT_BUFFER:RefCell<std::collections::VecDeque<String>>=RefCell::new(std::collections::VecDeque::new());
    }

    #[macro_export]
    macro_rules! input_internal {
        ($x:ident : $t:ty) => {
            INPUT_BUFFER.with(|p| {
                if p.borrow().len() == 0 {
                    let temp_str = input_line_str();
                    let mut split_result_iter = temp_str
                        .split(SPLIT_DELIMITER)
                        .map(|q| q.to_string())
                        .collect::<std::collections::VecDeque<_>>();
                    p.borrow_mut().append(&mut split_result_iter)
                }
            });
            let mut buf_split_result = String::new();
            INPUT_BUFFER.with(|p| buf_split_result = p.borrow_mut().pop_front().unwrap());
            let $x: $t = buf_split_result.parse().unwrap();
        };
        (mut $x:ident : $t:ty) => {
            INPUT_BUFFER.with(|p| {
                if p.borrow().len() == 0 {
                    let temp_str = input_line_str();
                    let mut split_result_iter = temp_str
                        .split(SPLIT_DELIMITER)
                        .map(|q| q.to_string())
                        .collect::<std::collections::VecDeque<_>>();
                    p.borrow_mut().append(&mut split_result_iter)
                }
            });
            let mut buf_split_result = String::new();
            INPUT_BUFFER.with(|p| buf_split_result = p.borrow_mut().pop_front().unwrap());
            let mut $x: $t = buf_split_result.parse().unwrap();
        };
    }

    #[macro_export]
    macro_rules! inputv {
    ($i:ident : $t:ty) => {
        input_internal!{$i : $t}
    };
    (mut $i:ident : $t:ty) => {
        input_internal!{mut $i : $t}
    };
    ($i:ident : $t:ty $(,)*) => {
            input_internal!{$i : $t}
    };
    (mut $i:ident : $t:ty $(,)*) => {
            input_internal!{mut $i : $t}
    };
    (mut $i:ident : $t:ty,$($q:tt)*) => {
            input_internal!{mut $i : $t}
            inputv!{$($q)*}
    };
    ($i:ident : $t:ty,$($q:tt)*) => {
            input_internal!{$i : $t}
            inputv!{$($q)*}
    };
}

    pub fn input_all() {
        INPUT_BUFFER.with(|p| {
            if p.borrow().len() == 0 {
                let mut temp_str = String::new();
                std::io::stdin().read_to_string(&mut temp_str).unwrap();
                let mut split_result_iter = temp_str
                    .split_whitespace()
                    .map(|q| q.to_string())
                    .collect::<std::collections::VecDeque<_>>();
                p.borrow_mut().append(&mut split_result_iter)
            }
        });
    }

    pub fn input_line_str() -> String {
        let mut s = String::new();
        io::stdin().read_line(&mut s).unwrap();
        s.trim().to_string()
    }

    #[allow(clippy::match_wild_err_arm)]
    pub fn input_vector<T>() -> Vec<T>
    where
        T: std::str::FromStr,
    {
        let mut v: Vec<T> = Vec::new();

        let s = input_line_str();
        let split_result = s.split(SPLIT_DELIMITER);
        for z in split_result {
            let buf = match z.parse() {
                Ok(r) => r,
                Err(_) => panic!("Parse Error",),
            };
            v.push(buf);
        }
        v
    }

    #[allow(clippy::match_wild_err_arm)]
    pub fn input_vector_row<T>(n: usize) -> Vec<T>
    where
        T: std::str::FromStr,
    {
        let mut v = Vec::with_capacity(n);
        for _ in 0..n {
            let buf = match input_line_str().parse() {
                Ok(r) => r,
                Err(_) => panic!("Parse Error",),
            };
            v.push(buf);
        }
        v
    }

    pub trait ToCharVec {
        fn to_charvec(&self) -> Vec<char>;
    }

    impl ToCharVec for String {
        fn to_charvec(&self) -> Vec<char> {
            self.to_string().chars().collect::<Vec<_>>()
        }
    }
}


struct Scan {
    buffer: std::collections::VecDeque<String>
}

impl Scan {
    fn new() -> Scan {
        Scan { buffer: std::collections::VecDeque::new() }
    }

    fn next<T: std::str::FromStr>(&mut self)-> T {
        loop {
            if let Some(token) = self.buffer.pop_front() {
                break token.parse::<T>().ok().unwrap();
            }
            let mut line = String::new();
            std::io::stdin().read_line(&mut line).expect("Fail to read");
            self.buffer = line.split_whitespace().map(String::from).collect();
        }
    }

    fn next_n<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.next::<T>()).collect()
    }

}

fn _main() {
    let mut scan = Scan::new();
    let n: usize = scan.next();
    let arr: Vec<isize> = scan.next_n(n);
    let allones: usize = arr.iter().filter(|&&x| x==1).count();
    let total: isize = arr.iter().sum();
    // convert to an array in which Kadane can be used
    let arr2: Vec<isize> = arr.into_iter().map(|x| if x==1 { -1 } else { 1 }).collect();
    let mut cnt: isize = 0;
    let mut maxcnt: isize = 0;
    if allones == n {
        println!("{}", total-1);
        return;
    }
    for i in 0..n {
        cnt += arr2[i];
        if cnt < 0 { cnt = 0; }
        maxcnt = maxcnt.max(cnt);
    }
    println!("{}", total + maxcnt);
}

fn main() {
    std::thread::Builder::new()
        .stack_size(1<<23).spawn(_main).unwrap().join().unwrap();
}


macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

fn num_of_1_before(i: &Vec<u32>, idx: usize) -> u32 {
    i.iter().take(idx).sum()
}

fn num_of_1_after(i: &Vec<u32>, idx: usize) -> u32 {
    i.iter().skip(idx + 1).sum()
}

fn max_num_of_1_flipped_after(i: &Vec<u32>, idx: usize) -> u32 {
    if 1 == *i.iter().nth(idx).unwrap() {
        return 0;
    }
    let targets = i.iter().skip(idx);
    let mut current_score = 0;
    let mut scores = Vec::new();
    for (local_index, value) in targets.enumerate() {
        if *value == 0 {
            current_score = current_score + 1;
        }
        scores.push(current_score + num_of_1_after(i, idx + local_index));
    }
    scores.into_iter().max().unwrap_or(0)
}

fn max_score(i: &Vec<u32>, idx: usize) -> u32 {
    num_of_1_before(i, idx) + max_num_of_1_flipped_after(i, idx)
}

fn main() {
    input! {
        n: usize,
        a: [u32; n],
    }

    let v = Vec::from(a);

    println!(
        "{}",
        (0..n).map(|idx| max_score(&v, idx)).max().unwrap_or(0)
    );
}


#![allow(dead_code, unused_macros, unused_imports)]
use std::{cell::{Cell, RefCell, UnsafeCell}, cmp::{Ordering, Reverse, max, min}, collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque, hash_map::{DefaultHasher, RandomState}}, error::Error, fmt::{Display, Write as FmtWrite}, hash::{BuildHasher, Hash, Hasher}, io::{BufWriter, Read, Stdin, Stdout, Write}, iter::{FromIterator, Peekable}, mem::swap, ops::*, process::exit, rc::Rc, str::{FromStr, from_utf8_unchecked}, time::{Duration, Instant}, convert::TryInto, marker::PhantomData};

const IO_BUF_SIZE: usize = 1 << 16;
type Input = Scanner<Stdin>;
type Output = BufWriter<Stdout>;
fn _init_input() -> Input { Scanner::new(std::io::stdin()) }
fn _init_output() -> Output { BufWriter::with_capacity(IO_BUF_SIZE, std::io::stdout()) }

#[repr(transparent)] struct Unsync<T>(T);
unsafe impl<T> Sync for Unsync<T> {}

type BadLazy<T> = Unsync<UnsafeCell<Option<T>>>;
impl<T> BadLazy<T> {
    const fn new() -> Self { Self(UnsafeCell::new(None)) }
}

static INPUT: BadLazy<Input> = BadLazy::new();
static OUTPUT: BadLazy<Output> = BadLazy::new();

fn inp<F: FnOnce(&mut Input) -> R, R>(f: F) -> R {
    unsafe { f((&mut *INPUT.0.get()).get_or_insert_with(_init_input)) }
}
fn out<F: FnOnce(&mut Output) -> R, R>(f: F) -> R {
    unsafe { f((&mut *OUTPUT.0.get()).get_or_insert_with(_init_output)) }
}

macro_rules! read {
    () => { read() };
    ($t: ty) => { read::<$t>() };
    ($t: ty, $($tt: ty),*) => { (read::<$t>(), $(read::<$tt>(),)*) };
    [$t: ty; $n: expr] => { read_vec::<$t>($n) };
}
macro_rules! println {
    () => { out(|x| { let _ = writeln!(x); }) };
    ($exp: expr) => { out(|x| { let _ = writeln!(x, "{}", $exp); }) };
    ($fmt: expr, $($arg : tt )*) => { out(|x| { let _ = writeln!(x, $fmt, $($arg)*); }) }
}
macro_rules! print {
    ($exp: expr) => { out(|x| { let _ = write!(x, "{}", $exp); }) };
    ($fmt: expr, $($arg : tt )*) => { out(|x| { let _ = write!(x, $fmt, $($arg)*); }) }
}

fn out_flush() { out(|x| { let _ = x.flush(); }); }

fn input_is_eof() -> bool { inp(|x| x.eof()) }
fn read_byte() -> u8 { inp(|x| x.byte()) }
fn read_bytes_no_skip(n: usize) -> Vec<u8> { inp(|x| x.bytes_no_skip(n)) }
fn read_bytes(n: usize) -> Vec<u8> { inp(|x| x.bytes(n)) }
fn read_bytes2(n: usize, m: usize) -> Vec<Vec<u8>> { inp(|x| x.bytes2(n, m)) }
fn read_token() -> Vec<u8> { inp(|x| x.token_bytes()) }
fn read_token_str() -> String { unsafe { String::from_utf8_unchecked(read_token()) } }
fn read_line() -> Vec<u8> { inp(|x| x.line_bytes()) }
fn read_line_str() -> String { unsafe { String::from_utf8_unchecked(read_line()) } }
fn read<T: FromStr>() -> T { read_token_str().parse::<T>().ok().expect("failed parse") }
fn read_vec<T: FromStr>(n: usize) -> Vec<T> { (0..n).map(|_| read()).collect() }
fn read_vec2<T: FromStr>(n: usize, m: usize) -> Vec<Vec<T>> { (0..n).map(|_| read_vec(m)).collect() }

struct Scanner<R: Read> {
    src: R,
    _buf: Vec<u8>,
    _pt: usize, // pointer
    _rd: usize, // bytes read
}

#[allow(dead_code)]
impl<R: Read> Scanner<R> {
    fn new(src: R) -> Scanner<R> {
        Scanner { src, _buf: vec![0; IO_BUF_SIZE], _pt: 1, _rd: 1 }
    }

    fn _check_buf(&mut self) {
        if self._pt == self._rd {
            self._rd = self.src.read(&mut self._buf).unwrap_or(0);
            self._pt = (self._rd == 0) as usize;
        }
    }

    // returns true if end of file
    fn eof(&mut self) -> bool {
        self._check_buf();
        self._rd == 0
    }

    // filters \r, returns \0 if eof
    fn byte(&mut self) -> u8 {
        loop {
            self._check_buf();
            if self._rd == 0 { return 0; }
            let res = self._buf[self._pt];
            self._pt += 1;
            if res != b'\r' { return res; }
        }
    }

    fn bytes_no_skip(&mut self, n: usize) -> Vec<u8> { (0..n).map(|_| self.byte()).collect() }
    fn bytes(&mut self, n: usize) -> Vec<u8> {
        let res = self.bytes_no_skip(n);
        self.byte();
        res
    }
    fn bytes2(&mut self, n: usize, m: usize) -> Vec<Vec<u8>> { (0..n).map(|_| self.bytes(m)).collect() }

    fn token_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c <= b' ' {
            if c == b'\0' { return res; }
            c = self.byte();
        }
        loop {
            res.push(c);
            c = self.byte();
            if c <= b' ' { return res; }
        }
    }

    fn line_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c != b'\n' && c != b'\0' {
            res.push(c);
            c = self.byte();
        }
        res
    }
}

trait JoinToStr {
    fn join_to_str(self, sep: &str) -> String;
    fn concat_to_str(self) -> String;
}
impl<T: Display, I: Iterator<Item = T>> JoinToStr for I {
    fn join_to_str(mut self, sep: &str) -> String {
        match self.next() {
            Some(first) => {
                let mut res = first.to_string();
                while let Some(item) = self.next() {
                    res.push_str(sep);
                    res.push_str(&item.to_string());
                }
                res
            }
            None => { String::new() }
        }
    }

    fn concat_to_str(self) -> String {
        let mut res = String::new();
        for item in self { res.push_str(&item.to_string()); }
        res
    }
}
trait AsStr { fn as_str(&self) -> &str; }
impl AsStr for [u8] { fn as_str(&self) -> &str {std::str::from_utf8(self).expect("attempt to convert non-UTF8 byte string.")} }

macro_rules! veci {
    ($n:expr , $i:ident : $gen:expr) => {{
        let _veci_n = $n;
        let mut _veci_list = Vec::with_capacity(_veci_n);
        for $i in 0.._veci_n {
            _veci_list.push($gen);
        }
        _veci_list
    }};
    ($n:expr , $gen:expr) => { veci!($n, _veci_: $gen) }
}

fn abs_diff<T: Sub<Output = T> + PartialOrd>(x: T, y: T) -> T {
    if x < y { y - x } else { x - y }
}

trait CommonNumExt {
    fn div_ceil(self, b: Self) -> Self;
    fn div_floor(self, b: Self) -> Self;
    fn gcd(self, b: Self) -> Self;
    fn highest_one(self) -> Self;
    fn lowest_one(self) -> Self;
    fn sig_bits(self) -> u32;
}

macro_rules! impl_common_num_ext {
    ($($ix:tt = $ux:tt),*) => {
        $(
            impl CommonNumExt for $ux {
                fn div_ceil(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if r != 0 { q + 1 } else { q }
                }
                fn div_floor(self, b: Self) -> Self { self / b }
                fn gcd(self, mut b: Self) -> Self {
                    let mut a = self; while a != 0 { swap(&mut a, &mut b); a %= b; }
                    b
                }
                #[inline] fn highest_one(self) -> Self {
                    if self == 0 { 0 } else { const ONE: $ux = 1; ONE << self.sig_bits() - 1 }
                }
                #[inline] fn lowest_one(self) -> Self { self & self.wrapping_neg() }
                #[inline] fn sig_bits(self) -> u32 { std::mem::size_of::<$ux>() as u32 * 8 - self.leading_zeros() }
            }

            impl CommonNumExt for $ix {
                fn div_ceil(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if self ^ b >= 0 && r != 0 { q + 1 } else { q }
                }
                fn div_floor(self, b: Self) -> Self {
                    let q = self / b; let r = self % b;
                    if self ^ b < 0 && r != 0 { q - 1 } else { q }
                }
                fn gcd(self, mut b: Self) -> Self {
                    let mut a = self; while a != 0 { swap(&mut a, &mut b); a %= b; }
                    b.abs()
                }
                #[inline] fn highest_one(self) -> Self { (self as $ux).highest_one() as _ }
                #[inline] fn lowest_one(self) -> Self { self & self.wrapping_neg() }
                #[inline] fn sig_bits(self) -> u32 { std::mem::size_of::<$ix>() as u32 * 8 - self.leading_zeros() }
            }
        )*
    }
}
impl_common_num_ext!(i8 = u8, i16 = u16, i32 = u32, i64 = u64, i128 = u128, isize = usize);

trait ChMaxMin<T> {
    fn chmax(&mut self, v: T) -> bool;
    fn chmin(&mut self, v: T) -> bool;
}
impl<T: PartialOrd> ChMaxMin<T> for Option<T> {
    fn chmax(&mut self, v: T) -> bool { if self.is_none() || v > *self.as_ref().unwrap() { *self = Some(v); true } else { false } }
    fn chmin(&mut self, v: T) -> bool { if self.is_none() || v < *self.as_ref().unwrap() { *self = Some(v); true } else { false } }
}
impl<T: PartialOrd> ChMaxMin<T> for T {
    fn chmax(&mut self, v: T) -> bool { if v > *self { *self = v; true } else { false } }
    fn chmin(&mut self, v: T) -> bool { if v < *self { *self = v; true } else { false } }
}

// * end commons * //

#[macro_use]
#[allow(dead_code)]
mod modint {
    use std::{fmt::{Display, Formatter}, marker::PhantomData, mem::swap, ops::*, str::FromStr, cell::Cell};
    use crate::ModInt;

    pub trait RemEuclidU32: Copy {
        /// Calculates `self` _mod_ `modulus` losslessly.
        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);
    #[inline]
    pub fn mul_mod_u32(a: u32, b: u32, m: u32) -> u32 {
        (a as u64 * b as u64 % m as u64) as u32
    }

    // for a, b < m, unspecified otherwise
    #[inline]
    fn add_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.wrapping_sub(m).overflowing_add(b);
        if c { r } else { a + b }
    }
    #[inline]
    fn sub_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.overflowing_sub(b);
        if c { r.wrapping_add(m) } else { r }
    }
    fn pow_mod_raw(a: u32, mut k: u64, m: u32) -> u32 {
        if m == 1 { return 0; }
        let mut a = a as u64;
        let m = m as u64;
        let mut r: u64 = 1;
        while k > 0 {
            if k & 1 == 1 {
                r = r * a % m;
            }
            k >>= 1;
            a = a * a % m;
        }
        r as u32
    }

    /// # Parameters
    /// * `b` `1 <= b`
    /// # Returns
    /// (x, g) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = a.rem_euclid(b);
        if a == 0 { return (0, b); }
        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; }
        (m0, s)
    }

    pub trait Modulus: Copy + Eq {
        fn get_modulus() -> u32;
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash)]
    #[repr(transparent)]
    pub struct ModIntBase<M: Modulus> {
        val: u32,
        _phantom: PhantomData<M>
    }

    impl <M: Modulus> ModIntBase<M> {
        #[inline(always)]
        pub fn modulus() -> u32 { M::get_modulus() }
        #[inline] pub fn new<I: RemEuclidU32>(val: I) -> Self { Self::raw(val.rem_euclid_u32(Self::modulus())) }
        #[inline] pub fn raw(val: u32) -> Self { Self { val, _phantom: PhantomData } }
        pub fn inv(self) -> Self {
            let (x, gcd) = inv_gcd(self.val.into(), Self::modulus().into());
            debug_assert!(gcd == 1, "the multiplicative inverse {}^-1 mod {} does not exist", self.val, Self::modulus());
            Self::raw(x as u32)
        }
        #[inline] pub fn val(self) -> u32 { self.val }
        #[inline] pub fn pow(self, k: u64) -> Self {
            Self::raw(pow_mod_raw(self.val, k, Self::modulus()))
        }
        pub fn powi(self, k: i64) -> Self { if k < 0 { self.inv().pow(-k as _) } else { self.pow(k as _) } }
        pub fn pow_vec(self, n: usize) -> Vec<Self> {
            let mut res = vec![Self::raw(0); n+1];
            res[0] += 1;
            for i in 1..=n {
                res[i] = res[i-1] * self;
            }
            res
        }

        pub fn invs(a: &[Self]) -> Vec<Self> {
            let n = a.len();
            if n == 0 { return vec![]; }
            let mut acc = Self::new(1);
            let mut res = Vec::with_capacity(n);
            for i in 0..n {
                if a[i].val() != 0 { acc *= a[i]; }
                res.push(acc);
            }
            acc = acc.inv();
            for i in (1..n).rev() {
                res[i] = acc * res[i-1];
                if a[i].val() != 0 { acc *= a[i]; }
            }
            res[0] = acc;
            res
        }
    }

    #[inline]
    pub fn mi<I: RemEuclidU32>(val: I) -> ModInt { ModIntBase::new(val) }
    #[inline] pub fn mir(v: u32) -> ModInt { ModIntBase::raw(v) }

    impl<V: RemEuclidU32, M: Modulus> From<V> for ModIntBase<M> {
        #[inline]
        fn from(from: V) -> Self { Self::new(from) }
    }
    impl<M: Modulus> Default for ModIntBase<M> {
        fn default() -> Self { Self::raw(0) }
    }
    impl<M: Modulus> FromStr for ModIntBase<M> {
        type Err = std::convert::Infallible;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(s.parse::<i64>()
            .map(Self::new)
            .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }
    }
    impl<M: Modulus> Display for ModIntBase<M> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
            self.val.fmt(f)
        }
    }
    impl<M: Modulus> std::fmt::Debug for ModIntBase<M> {
        #[inline]
        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.val, f)
        }
    }
    impl<M: Modulus> Neg for ModIntBase<M> {
        type Output = Self;

        #[inline]
        fn neg(self) -> Self::Output {
            Self::raw(0) - self
        }
    }

    impl<V: Into<ModIntBase<M>>, M: Modulus> Add<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn add(self, rhs: V) -> Self::Output {
            Self::raw(add_mod_raw(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Sub<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn sub(self, rhs: V) -> Self::Output {
            Self::raw(sub_mod_raw(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Mul<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn mul(self, rhs: V) -> Self::Output {
            Self::raw(mul_mod_u32(self.val, rhs.into().val, Self::modulus()))
        }
    }
    impl<V: Into<ModIntBase<M>>, M: Modulus> Div<V> for ModIntBase<M> {
        type Output = Self;
        #[inline]
        fn div(self, rhs: V) -> Self::Output { self * rhs.into().inv() }
    }

    impl <V: Into<ModIntBase<M>>, M: Modulus> AddAssign<V> for ModIntBase<M> {
        #[inline]
        fn add_assign(&mut self, rhs: V) { *self = *self + rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> SubAssign<V> for ModIntBase<M> {
        #[inline]
        fn sub_assign(&mut self, rhs: V) { *self = *self - rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> MulAssign<V> for ModIntBase<M> {
        #[inline]
        fn mul_assign(&mut self, rhs: V) { *self = *self * rhs; }
    }
    impl <V: Into<ModIntBase<M>>, M: Modulus> DivAssign<V> for ModIntBase<M> {
        #[inline]
        fn div_assign(&mut self, rhs: V) { *self = *self / rhs; }
    }

    impl <M: Modulus> std::iter::Sum for ModIntBase<M> {
        #[inline] fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::raw(0), Add::add)
        }
    }
    impl <M: Modulus> std::iter::Product for ModIntBase<M> {
        #[inline] fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(1.into(), Mul::mul)
        }
    }
    impl<'a, M: Modulus> std::iter::Sum<&'a Self> for ModIntBase<M> {
        #[inline] fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> ModIntBase<M> {
            iter.fold(Self::raw(0), |a, &b| a + b)
        }
    }
    impl<'a, M: Modulus> std::iter::Product<&'a Self> for ModIntBase<M> {
        #[inline] fn product<I: Iterator<Item = &'a Self>>(iter: I) -> ModIntBase<M> {
            iter.fold(1.into(), |a, &b| a * b)
        }
    }

    macro_rules! const_modulus {
        ($mint: ident, $name: ident, $modulus: expr) => {
            #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
            pub enum $name {}
            impl Modulus for $name {
                #[inline(always)] fn get_modulus() -> u32 { $modulus }
            }
            pub type $mint = ModIntBase<$name>;
        }
    }

    macro_rules! dynamic_modulus {
        ($mint: ident, $name: ident, $modulus: ident) => {
            static $modulus: crate::Unsync<Cell<u32>> = crate::Unsync(Cell::new(0));
            #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
            pub enum $name {}
            impl Modulus for $name {
                fn get_modulus() -> u32 { $modulus.0.get() }
            }
            impl $name {
                pub fn set_modulus(val: u32) { $modulus.0.set(val) }
            }
            pub type $mint = ModIntBase<$name>;
        }
    }

    const_modulus!(ModInt998_244_353, Mod998_244_353, 998_244_353);
    const_modulus!(ModInt1_000_000_007, Mod1_000_000_007, 1_000_000_007);
    dynamic_modulus!(DynamicModInt, DynamicModulus, DYNAMIC_MODULUS);
}

use crate::modint::*;
type ModInt = ModInt998_244_353;
// type ModInt = ModInt1_000_000_007;
// const_modulus!(ModInt, DefaultModulus, 1_000_000_009);
// type ModInt = DynamicModInt;

fn mod_factorials(maxn: usize) -> Vec<ModInt> {
    let mut res = vec![ModInt::default(); maxn+1];
    res[0] = 1.into();
    for i in 1..=maxn {
        res[i] = res[i-1] * i
    }
    return res;
}

struct ModCombinatorics {
    factorials: Vec<ModInt>,
    inv_factorials: Vec<ModInt>
}
#[allow(non_snake_case)]
impl ModCombinatorics {
    fn new(maxn: usize) -> Self {
        let factorials = mod_factorials(maxn);
        let mut inv = vec![ModInt::default(); maxn+1];
        inv[maxn] = factorials[maxn].inv();
        for i in (1..=maxn).rev() {
            inv[i-1] = inv[i] * i;
        }
        Self { factorials, inv_factorials: inv }
    }
    #[inline]
    fn factorial(&self, n: usize) -> ModInt { self.factorials[n] }
    #[inline]
    fn inv_factorial(&self, n: usize) -> ModInt { self.inv_factorials[n] }
    fn P(&self, n: usize, k: usize) -> ModInt {
        if k > n { ModInt::raw(0) } else { self.factorial(n) * self.inv_factorial(n-k) }
    }
    fn C(&self, n: usize, k: usize) -> ModInt {
        if k > n { ModInt::raw(0) } else { self.factorial(n) * self.inv_factorial(k) * self.inv_factorial(n-k) }
    }

    // multi-choose, be sure to adjust maxn accordingly
    fn M(&self, n: usize, k: usize) -> ModInt {
        if k == 0 { 1.into() } else { self.C(n + k - 1, k) }
    }
}

pub struct ModFft {
    n_inv: ModInt,
    w: Vec<ModInt>
}
impl ModFft {
    pub fn primitive_root() -> ModInt { ModInt::raw(3) /* for 998244353 */}
    pub fn good_len(deg: usize) -> usize { (deg + 1).next_power_of_two() }
    pub fn prepare(arr: &[ModInt], deg: usize) -> Vec<ModInt> {
        let n = Self::good_len(deg);
        let mut res = Vec::with_capacity(n);
        res.extend_from_slice(arr);
        res.resize(n, ModInt::raw(0));
        res
    }

    pub fn new(max_deg: usize) -> Self {
        let n = Self::good_len(max_deg);
        Self {
            n_inv: ModInt::new(n).inv(),
            w: ModInt::pow_vec(Self::primitive_root().pow((ModInt::modulus() - 1) as u64 / n as u64), n-1)
        }
    }

    pub fn transform(&self, a: &mut [ModInt]) { self.transform_impl(a, false) }
    pub fn transform_inv(&self, a: &mut [ModInt]) { self.transform_impl(a, true) }

    pub fn fft(&self, a: &[ModInt]) -> Vec<ModInt> { self.fft_deg(a, a.len() - 1) }
    pub fn fft_deg(&self, a: &[ModInt], deg: usize) -> Vec<ModInt> {
        let mut a = Self::prepare(a, deg);
        self.transform(&mut a);
        a
    }
    pub fn fft_inv(&self, a: &[ModInt]) -> Vec<ModInt> {
        let mut a = Self::prepare(a, a.len() - 1);
        self.transform_inv(&mut a);
        a
    }

    pub fn max_deg(&self) -> usize { self.w.len() - 1 }

    #[inline] fn transform_impl(&self, a: &mut [ModInt], invert: bool) {
        let sz = a.len();
        if sz <= 1 { return }
        let n = self.w.len();
        debug_assert!(sz <= n && sz.is_power_of_two(), "Array size {} must be <= {} and a power of 2", sz, n);
        let sh = sz.leading_zeros() + 1;

        for i in 0..sz {
            let j = i.reverse_bits() >> sh;
            if i < j { a.swap(i, j) }
        }

        let mut len = 2usize;
        let mut ang = (n >> 1) as isize;
        if invert { ang = -ang; }
        while len <= sz {
            let h = len >> 1;
            for i in (0..sz).step_by(len) {
                let mut k = 0usize;
                for j in i..i+h {
                    let u = a[j];
                    let v = a[j+h] * self.w[k];
                    a[j] = u + v;
                    a[j+h] = u - v;
                    k = k.wrapping_add(ang as usize) & (n-1);
                }
            }
            len <<= 1;
            ang >>= 1;
        }

        if invert {
            let sz_inv = self.n_inv * (n / sz);
            for i in 0..sz { a[i] *= sz_inv; }
        }
    }

    pub fn mul(&self, a: &[ModInt], b: &[ModInt]) -> Vec<ModInt> {
        if a.is_empty() || b.is_empty() { return vec![]; }
        let deg = a.len() + b.len() - 2;
        debug_assert!(deg < self.w.len(), "FFT capacity {} too small for polynomial of degree {}", self.w.len(), deg);
        let mut a = Self::prepare(a, deg);
        let mut b = Self::prepare(b, deg);
        self.transform(&mut a);
        self.transform(&mut b);
        for i in 0..a.len() { a[i] *= b[i]; }
        self.transform_inv(&mut a);
        a.truncate(deg + 1);
        a
    }

    pub fn sq(&self, a: &[ModInt]) -> Vec<ModInt> {
        if a.is_empty() { return vec![]; }
        let deg = a.len() * 2 - 2;
        debug_assert!(deg < self.w.len(), "FFT capacity {} too small for polynomial of degree {}", self.w.len(), deg);
        let mut a = Self::prepare(a, deg);
        self.transform(&mut a);
        for i in 0..a.len() { let ai = a[i]; a[i] = ai * ai; }
        self.transform_inv(&mut a);
        a.truncate(deg + 1);
        a
    }

    pub fn pow(&self, a: &[ModInt], exp: usize) -> Vec<ModInt> {
        if a.is_empty() { return vec![]; }
        let deg = (a.len() - 1) * exp;
        debug_assert!(deg < self.w.len(), "FFT capacity {} too small for polynomial of degree {}", self.w.len(), deg);
        let mut a = Self::prepare(a, deg);
        self.transform(&mut a);
        for i in 0..a.len() { a[i] = a[i].pow(exp as u64) }
        self.transform_inv(&mut a);
        a.truncate(deg + 1);
        a
    }

    pub fn product(&self, mut polys: VecDeque<Vec<ModInt>>) -> Vec<ModInt> {
        while let Some(p) = polys.pop_front() {
            if let Some(q) = polys.pop_front() {
                polys.push_back(self.mul(&p, &q));
            } else { return p; }
        }

        vec![ModInt::new(1)]
    }
}

struct FactorMap {
    map: Vec<u32>
}
impl FactorMap {
    pub fn new(limit: usize) -> FactorMap {
        let limit = limit + 1;
        let mut map = vec![0; limit >> 1];
        for p in (3..limit).step_by(2) {
            if map[p >> 1] != 0 { continue; }
            let sq = p * p;
            if sq >= limit { break; }
            for i in (sq..limit).step_by(p*2) {
                if map[i >> 1] == 0 { map[i >> 1] = p as u32; }
            }
        }

        FactorMap { map }
    }

    pub fn least_prime_factor(&self, n: usize) -> usize {
        if n & 1 == 0 { return 2; }
        let p = self.map[n >> 1] as usize;
        if p == 0 { n } else { p }
    }

    pub fn factorize(&self, n: usize) -> FactorIterator {
        FactorIterator { fm: self, n }
    }

    pub fn is_prime(&self, n: usize) -> bool { n > 1 && self.least_prime_factor(n) == n }

    /// lists divisors, unsorted
    pub fn divisors(&self, mut n: usize) -> Vec<usize> {
        let mut res = vec![1];

        while n > 1 {
            let p = self.least_prime_factor(n);
            let mut x = 0;
            loop {
                n /= p;
                x += 1;
                if p != self.least_prime_factor(n) { break; }
            }
            for i in 0..res.len() {
                let mut a = res[i];
                for _ in 0..x {
                    a *= p;
                    res.push(a);
                }
            }
        }

        res
    }

    pub fn new_with_mobius(limit: usize) -> (FactorMap, Vec<i8>) {
        let fm = Self::new(limit);
        let mut mu = vec![1i8; limit + 1];
        mu[0] = 0;

        for i in 2..=limit {
            let p = fm.least_prime_factor(i);
            mu[i] = if p == fm.least_prime_factor(i/p) { 0 } else { -mu[i/p] };
        }

        (fm, mu)
    }
}
struct FactorIterator<'a> {
    fm: &'a FactorMap,
    n: usize
}
impl Iterator for FactorIterator<'_> {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        if self.n <= 1 { return None; }
        let p = self.fm.least_prime_factor(self.n);
        self.n /= p;
        Some(p)
    }

    fn size_hint(&self) -> (usize, Option<usize>) { (0, Some(32)) }
}

#[allow(non_snake_case, non_upper_case_globals)]
fn main() {
    let num_cases: usize = 1;//read();

    for _case_num in 1..=num_cases {
        let n = read!(usize);
        let k = read!(usize);

        let mc = ModCombinatorics::new(n);
        let ff = ModFft::new(min(n, k) * 2);
        let mu = FactorMap::new_with_mobius(n).1;

        let mut m = 0usize;
        let mut A = mi(0);

        let mut ans = mi(0);
        if n == 1 || k == 1 { ans = mi(1); }
        else {
            for i in 1..=n {
                if mu[i] == 0 { continue; }
                let mn = n.div_ceil(i);
                if m != mn {
                    m = mn;
                    let l = min(m, k);

                    let P = veci!(l+1, j: if j & 1 == 1 { -mc.inv_factorial(j) } else { mc.inv_factorial(j) });
                    let Q = veci!(l+1, j: mi(j).pow(m as _) * mc.inv_factorial(j));
                    let R = ff.mul(&P, &Q);
                    A = R[2..=l].iter().sum();
                }
                if mu[i] == 1 { ans += A; } else { ans -= A; }
            }
        }

        println!(ans);
    }

    out_flush();
}