#![warn(clippy::pedantic)]

use std::{io::stdin, ops::Div};

#[allow(
    clippy::cast_possible_truncation,
    clippy::cast_sign_loss,
    clippy::cast_precision_loss
)]
// FIXME: https://github.com/rust-lang/rust/issues/116226
fn isqrt(n: u64) -> u64 {
    (n as f64).sqrt().floor() as u64
}

fn calculate_score<I: IntoIterator<Item = (u64, u64)>>(races: I) -> u64 {
    races
        .into_iter()
        .map(|(t, r)| {
            // x(t-x) = r
            // tx-x^2 = r
            // x^2-tx+r = 0
            // [ x^2+px+q = 0  ==>  x = -p/2±sqrt((p/2)^2-q) ]
            // x = t/2 ± sqrt(t^2/4-r)
            // x = (t ± 2 * sqrt(t^2/4-r)) / 2
            // x = (t ± sqrt(t^2-4r)) / 2

            let d_squared = t.pow(2) - 4 * r;
            // add a little bias for perfect squares, and subtract 1 to get the x values that lie
            // inside r
            let d = isqrt(d_squared - 1) - 1;
            ((t - d).div(2), (t + d).div_ceil(2))
        })
        .map(|(min, max)| max - min + 1)
        .product()
}

fn make_races<F>(
    times_line: &str,
    records_line: &str,
    make_numbers: F,
) -> impl Iterator<Item = (u64, u64)>
where
    F: Fn(&[&str]) -> Vec<u64>,
{
    let do_line = |line: &str| {
        let parts: Vec<_> = line.split(' ').filter(|s| !s.is_empty()).skip(1).collect();
        make_numbers(&parts)
    };

    do_line(times_line).into_iter().zip(do_line(records_line))
}

fn main() {
    let mut lines = stdin().lines().map(Result::unwrap);

    let times = lines.next().unwrap();
    let records = lines.next().unwrap();

    println!(
        "{}",
        calculate_score(make_races(&times, &records, |parts| {
            parts.iter().map(|n| n.parse().unwrap()).collect()
        }))
    );

    println!(
        "{}",
        calculate_score(make_races(&times, &records, |parts| {
            vec![parts.iter().copied().collect::<String>().parse().unwrap()]
        }))
    );
}
