// use std::ops::{Index, IndexMut};
// use std::cmp::{Ordering, min, max};
// use std::collections::{BinaryHeap, BTreeMap};
// use std::collections::btree_map::Entry::{Occupied, Vacant};
// use std::clone::Clone;

fn getline() -> String{
    let mut res = String::new();
    std::io::stdin().read_line(&mut res).ok();
    res
}

macro_rules! readl {
    ($t: ty) => {
        {
            let s = getline();
            s.trim().parse::<$t>().unwrap()
        }
    };
    ($( $t: ty),+ ) => {
        {
            let s = getline();
            let mut iter = s.trim().split(' ');
            ($(iter.next().unwrap().parse::<$t>().unwrap(),)*) 
        }
    };
}

macro_rules! readlvec {
    ($t: ty) => {
        {
            let s = getline();
            let iter = s.trim().split(' ');
            iter.map(|x| x.parse().unwrap()).collect::<Vec<$t>>()
        }
    }
}

macro_rules! mvec {
    ($v: expr, $s: expr) => {
        vec![$v; $s]
    };
    ($v: expr, $s: expr, $($t: expr),*) => {
        vec![mvec!($v, $($t),*); $s]
    };
}

macro_rules! debug {
    ($x: expr) => {
        println!("{}: {:?}", stringify!($x), $x)
    }
}

fn printiter<'a, T>(v: &'a T)
where
    &'a T: std::iter::IntoIterator, 
    <&'a T as std::iter::IntoIterator>::Item: std::fmt::Display {
    for (i,e) in v.into_iter().enumerate() {
        if i != 0 {
            print!(" ");
        }
        print!("{}", e);
    }
    println!("");
}

trait BinarySearch {
    type E;
    fn lower_bound(&self, &(Self::E)) -> usize;
    fn upper_bound(&self, &(Self::E)) -> usize;
}

impl<T> BinarySearch for Vec<T>
        where T: std::cmp::Ord {
    type E = T;

    fn lower_bound(&self, e: &(Self::E)) -> usize {
         if self[0] >= *e {
             0
         } else {
            let mut ng = 0;
            let mut ok = self.len();
            while ok-ng > 1 {
                let m = (ok+ng)/2;
                if self[m] >= *e {
                    ok = m;
                } else {
                    ng = m;
                }
            }
            ok
         }
    }
    
    fn upper_bound(&self, e: &(Self::E)) -> usize {
        if self[0] > *e {
             0
         } else {
            let mut ng = 0;
            let mut ok = self.len();
            while ok-ng > 1 {
                let m = (ok+ng)/2;
                if self[m] > *e {
                    ok = m;
                } else {
                    ng = m;
                }
            }
            ok
         }
    }
}

macro_rules! make_modint {
    ($MOD: expr, $name: ident) => {
        struct $name {
            val: i64,
        }

        impl $name {
            fn new(x: i64) -> $name {
                let x = x%$MOD;
                $name{val: if x < 0 { x+$MOD } else { x }}
            }

            fn pow(&self, x: i64) -> $name {
                let mut res = $name::new(1);
                let mut tmp = x;
                let mut p = *self;
                while tmp != 0 {
                    if tmp&1 == 1 {
                        res *= p;
                    }
                    tmp = tmp>>1;
                    p = p*p;
                }
                res
            }

            fn inv(&self) -> $name {
                assert!(self.val != 0);
                let mut a = self.val;
                let mut b = $MOD;
                let mut u = 1;
                let mut v = 0;
                use std::mem::swap;
                while b != 0 {
                    let t = a/b;
                    a -= t*b;
                    swap(&mut a, &mut b);
                    u -= t*v;
                    swap(&mut u, &mut v);
                }
                $name::new(u)
            }
        }

        impl std::clone::Clone for $name {
            fn clone(&self) -> $name {
                $name{ val: self.val }
            }
        }

        impl std::marker::Copy for $name { }

        impl std::ops::Add for $name {
            type Output = $name;
            fn add(self, y: $name) -> $name {
                let tmp = self.val+y.val;
                $name{val: if tmp >= $MOD {tmp-$MOD} else {tmp}}
            }
        }

        impl std::ops::Neg for $name {
            type Output = $name;
            fn neg(self) -> $name {
                $name::new(self.val)
            }
        }

        impl std::ops::Sub for $name {
            type Output = $name;
            fn sub(self, other: $name) -> $name{
                let tmp = self.val-other.val;
                $name{val: if tmp < 0 {tmp+$MOD} else {tmp}}
            }
        }

        impl std::ops::Mul for $name {
            type Output = $name;
            fn mul(self, y: $name) -> $name {
                $name{val: (self.val*y.val)%$MOD}
            }
        }

        impl std::ops::Div for $name {
            type Output = $name;
            fn div(self, other: $name) -> $name {
                self*other.inv()
            }
        }

        impl std::fmt::Display for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}", self.val)
            }
        }

        impl std::ops::AddAssign for $name {
        fn add_assign(&mut self, other: $name) {
            *self = *self+other;
        }
        }

        impl std::ops::SubAssign for $name {
            fn sub_assign(&mut self, other: $name) {
                *self = *self-other;
            }
        }

        impl std::ops::MulAssign for $name {
            fn mul_assign(&mut self, other: $name) {
                *self = *self*other;
            }
        }

        impl std::ops::DivAssign for $name {
            fn div_assign(&mut self, other: $name) {
                *self = *self*other.inv();
            }
        }

        impl std::fmt::Debug for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}", self.val)
            }
        }
    }
}

make_modint!(1_000_000_000+7, ModInt);

fn mint(x: i64) -> ModInt {
    ModInt::new(x)
}

#[derive(Debug)]
struct ConvQuery<T> 
    where T: algebra::Field  {
    fac: Vec<T>,
    facinv: Vec<T>,
}

mod algebra {
    use std::ops::{Add, Mul, Neg, Sub, Div};
    use std;

    pub trait Zero {
        fn Zero() -> Self;
    }
    
    pub trait Monoid: Add<Self, Output=Self>+Zero 
        where Self : std::marker::Sized{
    }

    pub trait Group: Monoid+Neg+Sub<Self, Output=Self> {
    }

    pub trait Ring: Group+Mul<Self, Output=Self> {
    }

    pub trait One {
        fn One() -> Self;
    }

    pub trait Field: Ring+One+Div<Self, Output=Self> {
    }
}

impl algebra::One for ModInt {
    fn One() -> Self {
        ModInt{val: 1}
    }
}

impl algebra::Zero for ModInt {
    fn Zero() -> Self {
        ModInt{val: 0}
    }
}

impl algebra::Monoid for ModInt {}

impl algebra::Group for ModInt {}

impl algebra::Ring for ModInt {}

impl algebra::Field for ModInt {}

trait MapToi64 {
    fn map_to_number(i64) -> Self;
}

impl MapToi64 for ModInt {
    fn map_to_number(x: i64) -> ModInt {
        ModInt::new(x)
    }
}

impl<T> ConvQuery<T>
    where T: algebra::Field+MapToi64+std::clone::Clone {
    
    fn new(n: usize) -> Self {
        let mut fac = Vec::with_capacity(n+1);
        let mut facinv = Vec::with_capacity(n+1);
        fac.push(T::One());
        for x in 1..n+1 {
            let num = {
                let last = fac.last().unwrap();
                (*last).clone() * T::map_to_number(x as i64)
            };
            fac.push(num.clone());
        }
        let mut num = T::One()/fac.last().unwrap().clone();
        facinv.push(num.clone());
        for i in (0..n).rev() {
            num = num * T::map_to_number((i+1) as i64);
            facinv.push(num.clone());
        }
        facinv.reverse();
        ConvQuery {
            fac: fac,
            facinv: facinv,
        }
    }

    fn query(&self, n: usize, m: usize) -> T {
        self.fac[n].clone() * self.facinv[n-m].clone() * self.facinv[m].clone()
    }
}


fn main() {
    let (n, x, y) = readl!(usize, i64, i64);
    let mut c = Vec::with_capacity(n);
    let mut w = Vec::with_capacity(n);
    for _ in 0..n {
        let (a, b) = readl!(usize, i64);
        c.push(a);
        w.push(b);
    }
    let c = c;
    let w = w;

    let mut cw = std::collections::HashMap::new();
    for i in 0..n {
        let vec = cw.entry(c[i]).or_insert(Vec::new());
        vec.push(w[i]);
    }

    let mut com = Vec::new();
    let mut aaa = Vec::new();
    for (&c, vec) in &mut cw {
        vec.sort();
        let bo = vec.upper_bound(&(x-vec[0]));
        aaa.push((vec[0], c));
        if bo != 0 {
            com.push((vec[0], bo, c));
        }
        for i in bo..vec.len() {
            com.push((vec[i], 1, c));
        }
    }
    com.sort();
    aaa.sort();
    let com = com;

    // debug!(aaa);
    // debug!(com);
    let map = if aaa.len() > 1{
        let mic = aaa[0].1;
        let mi = aaa[0].0;
        let mi2 = aaa[1].0;
        let (mi, num, color) = com[0];
        let mut map = std::collections::HashMap::new();
        for &(val, num, color) in com.iter() {
            if color != mic && val+mi <= y {
                let t = map.entry(color).or_insert(0);
                *t += num;
            } else if color == mic && val+mi2 <= y {
                let t = map.entry(color).or_insert(0);
                *t += num;
            }
        }
        map
    } else {
        std::collections::HashMap::new()
    };

    // debug!(map);
    let conv = ConvQuery::new(n+2);
    let mut ans = mint(1);
    let mut sum = 0;
    for (_, &val) in &map {
        sum += val;
        ans *= conv.query(sum, val);
    }
    // debug!(map.len());
    println!("{}", ans);

    // let v = vec![1, 3, 3, 5];
    // println!("{}", v.upper_bound(&3));
}



Measured memory_bytes: 45568