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: Runtime Error)

#[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()
}

type BitSetElement = usize;

#[derive(Clone)]
struct BitSet {
    size: usize,
    storage: Vec<BitSetElement>,
}

impl BitSet {
    fn unit_size() -> usize {
        size_of::<BitSetElement>()
    }

    fn unit_size_bit() -> usize {
        8 * Self::unit_size()
    }

    fn new(size: usize, default: bool) -> BitSet {
        if size == 0 {
            return Self::empty();
        }

        let unit_size_bit = Self::unit_size_bit();
        let storage_size = (size - 1) / unit_size_bit + 1;
        let mut storage = Vec::new();
        storage.resize(storage_size, 0);

        if default {
            for i in 0..storage_size - 1 {
                storage[i] = (-1i8) as BitSetElement;
            }
            storage[storage_size - 1] =
                ((-1i8) as BitSetElement) >> (unit_size_bit - (size - 1) % unit_size_bit - 1);
        }
        BitSet {
            size: size,
            storage: storage,
        }
    }

    fn empty() -> BitSet {
        BitSet {
            size: 0,
            storage: Vec::new(),
        }
    }

    fn one() -> BitSet {
        Self::new(1, true)
    }

    fn len(&self) -> usize {
        self.size
    }

    fn set(&mut self, pos: usize) {
        self.storage[pos / Self::unit_size_bit()] |= 1 << (pos % Self::unit_size_bit());
    }

    fn unset(&mut self, pos: usize) {
        self.storage[pos / Self::unit_size_bit()] &= !(1 << (pos % Self::unit_size_bit()));
    }

    fn get(&self, pos: usize) -> bool {
        if pos >= self.size {
            return false;
        }
        self.storage[pos / Self::unit_size_bit()] & (1 << (pos % Self::unit_size_bit())) > 0
    }

    /// self.get(i) | other.get(i-shift)
    fn or_with_shift(&self, other: &BitSet, shift: usize) -> BitSet {
        if self.size == 0 && other.size == 0 {
            return self.clone();
        }

        let unit_size_bit = Self::unit_size_bit();
        let shift_elem = shift / unit_size_bit;
        let bit_size = max(self.size, other.size + shift);
        let byte_size = (bit_size - 1) / unit_size_bit + 1;
        let mut storage = Vec::with_capacity(byte_size);

        for i in 0..byte_size {
            storage.push(0);
            if shift_elem + 1 <= i && i < other.storage.len() + shift_elem + 1
                && shift % unit_size_bit > 0
            {
                storage[i] |=
                    other.storage[i - 1 - shift_elem] >> (unit_size_bit - shift % unit_size_bit);
            }
            if shift_elem <= i && i < other.storage.len() + shift_elem {
                storage[i] |= other.storage[i - shift_elem] << (shift % unit_size_bit);
            }
            if i < self.storage.len() {
                storage[i] |= self.storage[i];
            }
        }

        BitSet {
            size: bit_size,
            storage: storage,
        }
    }

    fn increase_size(&mut self, new_size: usize, v: bool) {
        if new_size <= self.size {
            return;
        }

        if self.size == 0 {
            *self = BitSet::new(new_size, v);
            return;
        }

        let unit_size_bit = Self::unit_size_bit();
        let current_bytes = self.storage.len();
        let new_bytes = (new_size - 1) / unit_size_bit + 1;

        if v {
            self.storage.resize(new_bytes, -1i8 as BitSetElement);

            let used_bits = (self.size - 1) % 8 + 1;
            let rem_in_current_byte = if current_bytes == new_bytes {
                new_size - self.size
            } else {
                8 - used_bits
            };

            if rem_in_current_byte > 0 {
                self.storage[current_bytes - 1] |= ((1 << rem_in_current_byte) - 1) << used_bits;
            }
        } else {
            self.storage.resize(new_bytes, 0);
        }

        self.size = new_size;
    }

    fn dump(&self) {
        if self.storage.is_empty() {
            return;
        }

        for x in self.storage.iter().rev().skip(1).rev() {
            print!("{:08b}", x);
        }
        let last_used_bits = (self.size - 1) % 8 + 1;
        print!("{:01$b}", self.storage.last().unwrap(), last_used_bits);
        println!("");
    }
}

#[derive(Clone)]
struct State {
    target_value: Option<BitSet>,
}

fn update_target(
    append_char: bool,
    append_len: usize,
    prev: &BitSet,
    len: usize,
    prev_len: usize,
    c: usize,
    d: usize,
) -> BitSet {
    let prev_start = len - prev_len;
    let start = len - prev_len - append_len;
    if d < start {
        BitSet::new(0, false)
    } else if c <= start {
        if d < prev_start {
            BitSet::new(d - start + 1, append_char)
        } else {
            let mut target = prev.clone();
            target.increase_size(prev.len() + append_len, append_char);
            target
        }
    } else if c < prev_start {
        let mut target = prev.clone();
        target.increase_size(prev.len() + (prev_start - c), append_char);
        target
    } else {
        prev.clone()
    }
}

fn update_state(
    append_char: bool,
    append_len: usize,
    prev_target: &BitSet,
    len: usize,
    prev_len: usize,
    c: usize,
    d: usize,
) -> State {
    State {
        target_value: Some(update_target(
            append_char,
            append_len,
            prev_target,
            len,
            prev_len,
            c,
            d,
        )),
    }
}

fn update_dp<R: Iterator<Item = usize>>(
    append_char_is_b: bool,
    range: R,
    v_main: usize,
    v_fixed: usize,
    dp: &Vec<State>,
    len_longest: usize,
    len: usize,
    c: usize,
    d: usize,
) -> State {
    for len_start in range {
        let prev_dp = &dp[(v_main - len_start) % len_longest];

        if v_main == len_start && v_fixed == 0 {
            return update_state(append_char_is_b, len_start, &BitSet::empty(), len, 0, c, d);
        } else if let Some(ref target) = prev_dp.target_value {
            return update_state(
                append_char_is_b,
                len_start,
                target,
                len,
                v_main + v_fixed - len_start,
                c,
                d,
            );
        }
    }

    State { target_value: None }
}

fn solve_query(a: usize, b: usize, c: usize, d: usize) {
    assert!(c <= d);

    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;

    // dp_a の更新時⇒aを減らしてdp_bを見る
    // dp_b の更新時⇒bを減らしてdp_aを見る
    // dp_aは1×len_longestだけ要る
    // dp_bはlen_longest×1だけ要る
    // → bを走査していくので結局dp_bのbは全領域要る
    let mut dp_b = Vec::<Vec<State>>::new();
    {
        let mut inner = Vec::new();
        inner.resize(len_longest, State { target_value: None });
        dp_b.resize(b + 1, inner);
    }

    let mut dp_a = Vec::<State>::with_capacity(b + 1);
    dp_a.resize(b + 1, State { target_value: None });
    for va in 0..a + 1 {
        for vb in 0..b + 1 {
            // Update 'A'
            // less 'B' is more preferable
            let updated_dp_a = update_dp(
                false,
                (1..min(len_longest, va) + 1).rev(),
                va,
                vb,
                &dp_b[vb],
                len_longest,
                len,
                c,
                d,
            );
            // Update 'B'
            // more 'A' is more preferable
            dp_b[vb][va % len_longest] = update_dp(
                true,
                1..min(len_longest, vb) + 1,
                vb,
                va,
                &dp_a,
                len_longest,
                len,
                c,
                d,
            );

            dp_a[vb % len_longest] = updated_dp_a;
        }
    }

    let answer = if let Some(ref target) = dp_a[b % len_longest].target_value {
        target
    } else if let Some(ref target) = dp_b[b][a % len_longest].target_value {
        target
    } else {
        return;
    };

    for i in 0..(d - c + 1) {
        if answer.get(d - c - i) {
            print!("B");
        } else {
            print!("A");
        }
    }

    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);
    }
}