Problem:
Score : 700 points

Problem Statement

10^{10^{10}} participants, including Takahashi, competed in two programming contests.
In each contest, all participants had distinct ranks from first through 10^{10^{10}}-th.

The score of a participant is the product of his/her ranks in the two contests.

Process the following Q queries:

In the i-th query, you are given two positive integers A_i and B_i. Assuming that Takahashi was ranked A_i-th in the first contest and B_i-th in the second contest, find the maximum possible number of participants whose scores are smaller than Takahashi's.

Constraints

1 \leq Q \leq 100

1\leq A_i,B_i\leq 10^9(1\leq i\leq Q)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

Q
A_1 B_1
:
A_Q B_Q

Output

For each query, print the maximum possible number of participants whose scores are smaller than Takahashi's.

Sample Input 1

8
1 4
10 5
3 3
4 11
8 9
22 40
8 36
314159265 358979323

Sample Output 1

1
12
4
11
14
57
31
671644785

Let us denote a participant who was ranked x-th in the first contest and y-th in the second contest as (x,y).

In the first query, (2,1) is a possible candidate of a participant whose score is smaller than Takahashi's. There are never two or more participants whose scores are smaller than Takahashi's, so we should print 1.

Solution in Rust (1.15.1) (judge verdict: Accepted)

#![allow(unused_imports)]
#![allow(non_snake_case)]

use procon::*;
use std::cmp::{max, min};
use std::collections::*;
use std::ops::*;
use std::*;

fn floor_sqrt(T: i64) -> i64 {
    if T <= 1 {
        return 0;
    }

    let mut L = 1;
    let mut R = T + 1;
    while R - L > 1 {
        let M = L + (R - L) / 2;

        // M * M < T ?
        let ok = {
            let q = T / M;
            let r = T % M;
            q == M && r > 0 || q > M
        };
        if ok {
            L = M;
        } else {
            R = M;
        }
    }
    L
}

pub fn calc(A: i64, B: i64) -> i64 {
    assert!(A <= B);

    // 高橋くんのスコア
    let T = A * B;

    // C: C^2 < T なる最大の整数
    let C = floor_sqrt(T);

    // ある参加者のコンテストの順位が A, B だったということを (A, B) で表す。
    // スコアが T 未満の参加者のスコアを S = A'*B' とおく。

    if A == B {
        // A'*B' < A^2 から A' < A または B' < A がいえて、 A' < A は最大 A-1 人、B' < A は最大 A-1 人、ゆえに最大値の上限は 2A - 2.
        // (1, 2A - 2), (2, 2A - 1), ... (A - 1, A - 1), ..., (2A - 2,  1) という結果がありうるのでこの上限が最大値になる。
        2 * A - 2
    } else if A + 1 == B {
        // A'*B' < A(A + 1) ゆえ A' <= A.
        // A' = A はありえないので (A位は高橋くんだから) 、 A' < A または B' <= A。
        // A' < A は A-1 人。
        // B' == A のとき A' < A なので A-1人。
        // 実際、 (1, 2A - 1), (2, 2A - 2), ..., (A, A), ..., (2A - 1, 1) という結果があるので上限が最大値になる。
        2 * A - 2
    } else if C * (C + 1) >= T {
        // このとき |A - B| >= 2 である。
        // C(C+1) >= AB とする。
        // A < C < C+1 < B である。(B <= C+1 なら (A <= B - 2 <= C - 1 なので) AB <= (C - 1)(C + 1) < C^2 < AB となり矛盾。)
        // A' <= C or B' <= C である。
        // (C - 1) + (C - 1) = 2C - 2 が上限になる?
        // 実際、次の2種類の結果の組み合わせの総和が 2C - 2 個なので上限になる。
        //  { (A - 1 - n, B + 1 + n) | 0 <= n <= A - 2 } (A - 2個)
        //  { (2C - n, n) | 1 <= n <= 2C - A - 1 } (2C - A - 1個)
        2 * C - 2
    } else {
        2 * C - 1
    }
}

pub fn main() {
    let Q = read_line().parse::<usize>().unwrap();
    for _ in 0..Q {
        let words = read_words::<i64>();
        let A = words[0];
        let B = words[1];
        println!("{}", calc(min(A, B), max(A, B)));
    }
    return;
}

#[test]
fn test_floor_sqrt() {
    assert_eq!(floor_sqrt(15), 3);
    assert_eq!(floor_sqrt(16), 3);
    assert_eq!(floor_sqrt(17), 4);
}

pub mod procon {
    use std;
    use std::collections::*;
    use std::io;
    use std::mem;
    use std::str::FromStr;

    pub fn read_line() -> String {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim_right().to_owned()
    }

    pub fn read_words<T>() -> Vec<T>
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.split_whitespace()
            .map(|word| T::from_str(word).unwrap())
            .collect()
    }

    pub fn read_vec(len: usize) -> Vec<String> {
        let mut vec = Vec::new();
        while vec.len() < len {
            let line = read_line();
            for word in line.split_whitespace() {
                vec.push(word.to_owned());
            }
        }
        assert!(vec.len() == len);
        vec
    }

    pub trait IteratorExt: Iterator {
        fn vec(self) -> Vec<Self::Item>
        where
            Self: Sized,
        {
            self.collect()
        }
    }

    impl<T: Iterator> IteratorExt for T {}
}