Problem:
Score : 1100 points

Problem Statement

Let f(A, B), where A and B are positive integers, be the string satisfying the following conditions:

f(A, B) has length A + B;

f(A, B) contains exactly A letters A and exactly B letters B;

The length of the longest substring of f(A, B) consisting of equal letters (ex., AAAAA or BBBB) is as small as possible under the conditions above;

f(A, B) is the lexicographically smallest string satisfying the conditions above.

For example, f(2, 3) = BABAB, and f(6, 4) = AABAABAABB.

Answer Q queries: find the substring of f(A_i, B_i) from position C_i to position D_i (1-based).

Constraints

1 \leq Q \leq 10^3

1 \leq A_i, B_i \leq 5 \times 10^8

1 \leq C_i \leq D_i \leq A_i + B_i

D_i - C_i + 1 \leq 100

All input values are integers.

Partial Score

500 points will be awarded for passing the testset satisfying 1 \leq A_i, B_i \leq 10^3.

Input

Input is given from Standard Input in the following format:

Q
A_1 B_1 C_1 D_1
A_2 B_2 C_2 D_2
:
A_Q B_Q C_Q D_Q

Output

For each query i in order of input, print a line containing the substring of f(A_i, B_i) from position C_i to position D_i (1-based).

Sample Input 1

5
2 3 1 5
6 4 1 10
2 3 4 4
6 4 3 7
8 10 5 8

Sample Output 1

BABAB
AABAABAABB
A
BAABA
ABAB

Solution in Rust (1.15.1) (judge verdict: Time Limit Exceeded)

#[allow(unused_imports)]
use std::io::*;
#[allow(unused_imports)]
use std::str::*;
#[allow(unused_imports)]
use std::mem::*;
#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
#[allow(unused_imports)]
use std::usize;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let mut line = String::new();
    stdin().read_line(&mut line).unwrap();
    line.trim().to_string().parse().ok().unwrap()
}

#[allow(dead_code)]
fn read_cols<T: FromStr>() -> Vec<T> {
    let mut line = String::new();
    stdin().read_line(&mut line).unwrap();

    line.trim()
        .split_whitespace()
        .map(|s| s.parse().ok().unwrap())
        .collect()
}

fn print_chars(s: &str, pos: usize, len: usize, c: usize, d: usize) {
    assert!(c <= d);

    if pos + len <= c {
        return;
    }

    if d < pos {
        return;
    }

    let print_min_pos = max(c, pos);
    let print_max_pos = min(pos + len - 1, d);

    for _ in 0..print_max_pos - print_min_pos + 1 {
        print!("{}", s);
    }
}

fn solve_query(a: usize, b: usize, c: usize, d: usize) {
    let len = a + b;

    let min_ab = min(a, b);
    let max_ab = max(a, b);
    let len_longest = (max_ab - 1) / (min_ab + 1) + 1;

    let mut va = a;
    let mut vb = b;
    let mut pos = 0;
    while pos <= d {
        if va * len_longest < vb {
            let next_len_b = min(len_longest, vb - (va * len_longest));
            print_chars("B", pos, next_len_b, c, d);
            pos += next_len_b;
            vb -= next_len_b;
        } else {
            let next_len_a = min(len_longest, va - (vb - 1) / len_longest);
            print_chars("A", pos, next_len_a, c, d);
            pos += next_len_a;
            va -= next_len_a;
            if vb >= 1 {
                print_chars("B", pos, 1, c, d);
                pos += 1;
                vb -= 1;
            }
        }
    }

    println!("");
}

fn main() {
    // 20:01:15
    let num_q = read::<usize>();
    for _ in 0..num_q {
        let query = read_cols::<usize>();
        solve_query(query[0], query[1], query[2] - 1, query[3] - 1);
    }
}