#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define rrep(i,n) for(int i = 1; i <= (n); ++i)
#define drep(i,n) for(int i = (n)-1; i >= 0; --i)
#define srep(i,s,t) for (int i = s; i < t; ++i)
#define rng(a) a.begin(),a.end()
using namespace std;
typedef long long int ll;
typedef pair<int,int> P;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<P> vp;
#define dame { puts("-1"); return 0;}
#define yn {puts("Yes");}else{puts("No");}
#define MAX_N 200005

const int MAX = 210000;
const int MOD = 1000000007;
long long fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void COMinit() {
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (int i = 2; i < MAX; i++){
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}
// 二項係数計算
long long COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

long long FINV(int n){
    if (n < 0) return 0;
    return finv[n];
}

int par[MAX_N]; // 親
int rank_[MAX_N]; // 木の深さ

// n要素で初期化
void UFinit(){
    for(int i=0;i<MAX_N;i++){
        par[i] = i;
        rank_[i] = 0;
    }
}

// 木の根を求める
int find(int x){
    if(par[x] == x){
        return x;
    }else{
        return par[x] = find(par[x]);
    }
}

// xとyの属する集合を併合
void unite(int x, int y){
    x = find(x);
    y = find(y);
    if(x == y) return;

    if(rank_[x] < rank_[y]){
        par[x] = y;
    }else{
        par[y] = x;
        if(rank_[x] == rank_[y]) rank_[x]++;
    }
}

// xとyが同じ集合に属するか否か
bool same(int x, int y){
    return find(x) == find(y);
}

vector<int> G[MAX_N];
vector<int> f[MAX_N];
int cnt[MAX_N];

int main() {
    int n,x,y;
    cin >> n >> x >> y;
    vector<P> v;
    rep(i,n){
        P p;
        cin >> p.second >> p.first;
        p.second--;
        v.push_back(p);
    }
    sort(v.begin(), v.end());
    UFinit();
    COMinit();

    // 異色Union
    int mi = v[0].first;
    int c = v[0].second;
    int arg_mi = 0;
    rep(i,n){
        if(c != v[i].second && mi + v[i].first <= y){
            unite(0, i);
        }
    }
    rep(i,n){
        if(c != v[i].second){
            c = v[i].second;
            mi = v[i].first;
            arg_mi = i;
            break;
        }
    }
    rep(i,n){
        if(c != v[i].second && mi + v[i].first <= y){
            unite(arg_mi, i);
        }
    }

        
    // 同色Union
    rep(i,n){
        G[v[i].second].push_back(i);
    }
    rep(i,n){
        if(G[i].size()>=2){
            srep(j,1,G[i].size()){
                if(v[G[i][0]].first + v[G[i][j]].first <= x){
                    unite(G[i][0], G[i][j]);
                }
            }
        }
    }

    // Unionチェック
    ll ans = 1;
    rep(i,n){
        f[find(i)].push_back(i);
    }
    rep(i,n){
        if(f[i].size() >= 2){
            int flag = 0;
            rep(j,f[i].size()){
                if(v[f[i][0]].second != v[f[i][j]].second){
                    flag = 1;
                    break;
                }
            }
            if(flag != 0){
                rep(j,MAX_N)cnt[j] = 0;
                rep(j,f[i].size()){
                    cnt[v[f[i][j]].second]++;
                }
                ans = fac[f[i].size()];
                rep(j,MAX_N){
                    if(cnt[j] > 0){
                        ans *= finv[cnt[j]];
                        ans %= MOD;
                    }
                }
                break;
            }
        }
    }

    cout << ans << endl;
    return 0;
}
 
 


Measured memory_bytes: 28272