import java.util.*;
import java.io.*;
public class EdC {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static char[][] grid;
    static int n;
    static int t;
    static int[][] dp;
    static int[] times;
    static int[] genre;
	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		out = new PrintWriter(System.out);
 		n = sc.nextInt();
 		t = sc.nextInt();
 		times = new int[n];
 		genre = new int[n];
 		for(int j =0 ;j<n;j++){
 			times[j] = sc.nextInt();
 			genre[j] = sc.nextInt();
 		}
 		dp = new int[1<<n][4];
 		for(int j = 0;j<1<<n;j++)
 			Arrays.fill(dp[j],  -1);
 		int ans = 0;
 		for(int j=0;j<1<<n;j++){
 			int time = 0;
 			for(int k = 0;k<n;k++){
 				if (((1<<k) & j) != 0){
 					time+=times[k];
 				}
 			}
 			if (time == t){
 				letsgodp(j, 1);
 				letsgodp(j, 2);
 				letsgodp(j, 3);
 				ans+=dp[j][1];
 				ans%=mod;
 				ans+=dp[j][2];
 				ans%=mod;
 				ans+=dp[j][3];
 				ans%=mod;
 			}
 		}
 		out.println(ans);
 		out.close();
 	}
	public static void letsgodp(int mask, int dg){
		if (dp[mask][dg] != -1)
			return;
		dp[mask][dg] = 0;
		for(int j = 0;j<n;j++){
			if (((1<<j) & mask) != 0 && genre[j] == dg){
				int submask = mask - (1<<j);
				int og1 = genre[j]+1 > 3 ? genre[j]-2 : genre[j]+1;
				int og2 = genre[j]+2 > 3 ? genre[j]-1 : genre[j]+2;
				if (submask != 0){
					letsgodp(submask, og1);
					letsgodp(submask, og2);
					dp[mask][dg] +=(dp[submask][og1] + dp[submask][og2]);
					dp[mask][dg] %=mod;
				}
				else{
					dp[mask][dg] = 1;
				}
			}
		}
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
	static void verdict(boolean a){
        out.println(a ? "YES" : "NO");
    }
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is

1185_G1. Playlist for Polycarp (easy version)


/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class ACMIND
{
    static FastReader scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<25)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }
    static int n, g[], t[], T;
    static int dp[][];
    static void solve() throws IOException
    {
        scan = new FastReader();
        pw = new PrintWriter(System.out,true);
        StringBuilder fast = new StringBuilder();
        n = ni();
        T = ni();
        g = new int[n];
        t = new int[n];
        for(int i=0;i<n;++i) {
            t[i] = ni();
            g[i] = ni();
        }
        int MAX = (1<<n);
        dp = new int[MAX][4];
        for(int i=0;i<MAX;++i) {
            for(int j=0;j<4;++j) {
                dp[i][j] = -1;
            }
        }
        pl(f((1<<n)-1,0));
        pw.flush();
        pw.close();
    }

    static int f(int mask, int prev) {
        if(dp[mask][prev]!=-1) {
            return dp[mask][prev];
        }
        int left = T;
        for(int i=0;i<n;++i) {
            if((mask&(1<<i))==0) {
                left-=t[i];
            }
        }
        if(left==0) {
            return 1;
        }
        int cnt = 0;
        for(int i=0;i<n;++i) {
            if((mask&(1<<i))!=0) {
                if(g[i]!=prev && left>=t[i]) {
                    cnt+=f(mask^(1<<i), g[i]);
                    if(cnt>=MOD) {
                        cnt-=MOD;
                    }
                }
            }
        }
        return dp[mask][prev] = cnt;
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;

public class G1 {
    static int n, T, duration[], type[];
    static long dp[][][], mod = (long) 1e9 + 7;

    public static void main(String[] args) throws Exception {
        new Thread(null, new Runnable() {
            public void run() {
                try {
                    solveIt();
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }, "Main", 1 << 28).start();
    }

    public static void solveIt() throws Exception {
        Scanner in = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = in.nextInt();
        T = in.nextInt();
        dp = new long[3][T + 1][1 << n];
        duration = new int[n];
        type = new int[n];
        for (int i = 0; i < n; i++) {
            duration[i] = in.nextInt();
            type[i] = in.nextInt() - 1;
        }
        for (long a[][] : dp) for (long b[] : a) Arrays.fill(b, -1);
        pw.println(solve(0, T, 0));

        pw.close();
    }

    static long solve(int lastType, int rem, int mask) {
        if (rem == 0) return 1;
        if (rem < 0) return 0;
        if (dp[lastType][rem][mask] != -1) return dp[lastType][rem][mask];
        long res = 0;
        for (int i = 0; i < n; i++) {
            if (!check(mask, i) && (lastType != type[i] || mask == 0) && rem - duration[i] >= 0) {
                res += solve(type[i], rem - duration[i], set(mask, i));
                if (res >= mod) res -= mod;
            }
        }
        return dp[lastType][rem][mask] = res;
    }

    static boolean check(int N, int pos) {
        return (N & (1 << pos)) != 0;
    }

    static int set(int N, int pos) {
        return N = N | (1 << pos);
    }

    static int reset(int N, int pos) {
        return N = N & ~(1 << pos);
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }
}


import java.io.*;
import java.util.*;

public class CF1185G2 {
	static final int MD = 1000000007;
	static int[][] solve1(int[] aa, int t, int n) {
		int[][] da = new int[t + 1][n + 1];
		da[0][0] = 1;
		for (int i = 0; i < n; i++) {
			int a = aa[i];
			for (int s = t - 1; s >= 0; s--)
				for (int m = 0; m < n; m++) {
					int x = da[s][m];
					if (x != 0) {
						int s_ = s + a;
						if (s_ <= t)
							da[s_][m + 1] = (da[s_][m + 1] + x) % MD;
					}
				}
		}
		return da;
	}
	static int[][][] solve2(int[] aa, int[] bb, int t, int na, int nb) {
		int[][] da = solve1(aa, t, na);
		int[][][] dab = new int[t + 1][na + 1][nb + 1];
		for (int s = 0; s <= t; s++)
			for (int ma = 0; ma <= na; ma++)
				dab[s][ma][0] = da[s][ma];
		for (int i = 0; i < nb; i++) {
			int b = bb[i];
			for (int s = t - 1; s >= 0; s--)
				for (int ma = 0; ma <= na; ma++)
					for (int mb = 0; mb < nb; mb++) {
						int x = dab[s][ma][mb];
						if (x != 0) {
							int s_ = s + b;
							if (s_ <= t)
								dab[s_][ma][mb + 1] = (dab[s_][ma][mb + 1] + x) % MD;
						}
					}
		}
		return dab;
	}
	static long power(int a, int k) {
		if (k == 0)
			return 1;
		long p = power(a, k / 2);
		p = p * p % MD;
		if (k % 2 == 1)
			p = p * a % MD;
		return p;
	}
	static int[] ff, gg;
	static int ch(int n, int k) {
		return (int) ((long) ff[n] * gg[n - k] % MD * gg[k] % MD);
	}
	static int[][][] init(int n, int na, int nb, int nc) {
		ff = new int[n + 1];
		gg = new int[n + 1];
		for (int i = 0, f = 1; i <= n; i++) {
			ff[i] = f;
			gg[i] = (int) power(f, MD - 2);
			f = (int) ((long) f * (i + 1) % MD);
		}
		int[][][] dp = new int[na + 1][nb + 1][nc + 1];
		for (int ma = 0; ma <= na; ma++)
			for (int mb = 0; mb <= nb; mb++)
				for (int mc = 0; mc <= nc; mc++) {
					int x = (int) ((long) ff[ma + mb + mc] * gg[ma] % MD * gg[mb] % MD * gg[mc] % MD);
					for (int ma_ = ma == 0 ? 0 : 1; ma_ <= ma; ma_++) {
						int cha = ma == 0 ? 1 : ch(ma - 1, ma_ - 1);
						for (int mb_ = mb == 0 ? 0 : 1; mb_ <= mb; mb_++) {
							int chb = mb == 0 ? 1 : ch(mb - 1, mb_ - 1);
							for (int mc_ = mc == 0 ? 0 : 1; mc_ <= mc; mc_++) {
								int chc = mc == 0 ? 1 : ch(mc - 1, mc_ - 1);
								int y = dp[ma_][mb_][mc_];
								if (y == 0)
									continue;
								x = (int) ((x - (long) y * cha % MD * chb % MD * chc) % MD);
							}
						}
					}
					if (x < 0)
						x += MD;
					dp[ma][mb][mc] = x;
				}
		for (int ma = 0; ma <= na; ma++)
			for (int mb = 0; mb <= nb; mb++)
				for (int mc = 0; mc <= nc; mc++)
					dp[ma][mb][mc] = (int) ((long) dp[ma][mb][mc] * ff[ma] % MD * ff[mb] % MD * ff[mc] % MD);
		return dp;
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int t = Integer.parseInt(st.nextToken());
		int[] aa = new int[n];
		int[] bb = new int[n];
		int[] cc = new int[n];
		int na = 0, nb = 0, nc = 0;
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());
			if (g == 1)
				aa[na++] = a;
			else if (g == 2)
				bb[nb++] = a;
			else
				cc[nc++] = a;
		}
		int[][][] dp = init(n, na, nb, nc);
		int[][][] dab = solve2(aa, bb, t, na, nb);
		int[][] dc = solve1(cc, t, nc);
		int ans = 0;
		for (int tab = 0; tab <= t; tab++) {
			int tc = t - tab;
			for (int ma = 0; ma <= na; ma++)
				for (int mb = 0; mb <= nb; mb++) {
					int xab = dab[tab][ma][mb];
					if (xab == 0)
						continue;
					for (int mc = 0; mc <= nc; mc++) {
						int xc = dc[tc][mc];
						if (xc == 0)
							continue;
						ans = (int) ((ans + (long) xab * xc * dp[ma][mb][mc]) % MD);
					}
				}
		}
		System.out.println(ans);
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

@SuppressWarnings("unused")
public class Solution{

	static long inf = (long)1e18+100;
	static final long mod = (long)1e9+7;

	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws IOException {
		FastScanner fs = new FastScanner();
    	PrintWriter out = new PrintWriter(System.out);

    	int tt = 1;
    	outer:
    	while(tt-->0) {

    		int n = fs.nextInt(), T = fs.nextInt();
    		int[] t = new int[n], g = new int[n];

    		for(int i=0;i<n;i++) {
    			t[i] = fs.nextInt(); g[i] = fs.nextInt();
    		}

    		//dp[mask][pre] -- number of ways to order mask songs last song has prev genre
    		long[][] dp = new long[1<<n][4];
    		dp[0][0] = 1;

    		long ans = 0;

    		for(int mask=0;mask<(1<<n);mask++) {
    			for(int pre=0;pre<=3;pre++) {
    				for(int i=0;i<n;i++)
    					if((mask&(1<<i))==0 && g[i]!=pre)
    						dp[mask^(1<<i)][g[i]] = add(dp[mask^(1<<i)][g[i]], dp[mask][pre]);
    				int sum = 0;
    				for(int i=0;i<n;i++) {
    					if((mask&(1<<i))!=0) sum += t[i];
    				}
    				if(sum==T) ans = add(ans, dp[mask][pre]);
    			}
    		}

    		out.println(ans);

    	}

    	out.close();
    }

	static long add(long a, long b) {
		a += b;
		if(a>mod) return a - mod;
		return a;
	}

    static final Random random=new Random();

    static <T> void shuffle(T[] arr) {
    	int n = arr.length;
    	for(int i=0;i<n;i++	) {
    		int k = random.nextInt(n);
    		T temp = arr[k]; arr[k] = arr[i]; arr[i] = temp;
    	}
    }

    static void ruffleSort(int[] a) {
    	int n=a.length;//shuffle, then sort
    	for (int i=0; i<n; i++) {
    		int oi=random.nextInt(n); int temp=a[oi];
    		a[oi]=a[i]; a[i]=temp;
    	}
    	Arrays.sort(a);
    }

    static void ruffleSort(long[] a) {
    	int n=a.length;//shuffle, then sort
    	for (int i=0; i<n; i++) {
    		int oi=random.nextInt(n); long temp=a[oi];
    		a[oi]=a[i]; a[i]=temp;
    	}
    	Arrays.sort(a);
    }

    static void reverse(int[] arr, int l, int r) {
    	for(int i=l;i<l+(r-l)/2;i++){
    		int temp = arr[i]; arr[i] = arr[r-i+l-1]; arr[r-i+l-1] = temp;
    	}
    }

    static void reverse(long[] arr, int l, int r) {
    	for(int i=l;i<l+(r-l)/2;i++){
    		long temp = arr[i]; arr[i] = arr[r-i+l-1]; arr[r-i+l-1] = temp;
    	}
    }

    static <T> void reverse(T[] arr, int l, int r) {
    	for(int i=l;i<l+(r-l)/2;i++) {
    		T temp = arr[i]; arr[i] = arr[r-i+l-1]; arr[r-i+l-1] = temp;
    	}
    }

    static class FastScanner{
    	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer st = new StringTokenizer("");

    	public String next(){
    		while(!st.hasMoreElements()){
    			try{
    				st = new StringTokenizer(br.readLine());
    			} catch(IOException e){
    				e.printStackTrace();
    			}
    		}
    		return st.nextToken();
    	}

    	public String nextLine() throws IOException {
    		return br.readLine();
    	}

    	public int nextInt(){
    		return Integer.parseInt(next());
    	}

    	public int[] readArray(int n){
    		int[] a = new int[n];
    		for(int i=0;i<n;i++)
    			a[i] = nextInt();
    		return a;
    	}

    	public long nextLong() {
    		return Long.parseLong(next());
    	}

    	public char nextChar() {
    		return next().toCharArray()[0];
    	}
    }

}


// Don't place your source in a package
import javax.swing.*;
import java.lang.reflect.Array;
import java.text.DecimalFormat;
import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.*;
import java.util.stream.Stream;

// Please name your class Main
public class Main {
    static FastScanner fs=new FastScanner();
    static class FastScanner {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer("");
        public String next() {
            while (!st.hasMoreElements())
                try {
                    st=new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return st.nextToken();
        }
        int Int() {
            return Integer.parseInt(next());
        }

        long Long() {
            return Long.parseLong(next());
        }

        String Str(){
            return next();
        }
    }

    public static void main (String[] args) throws java.lang.Exception {
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

        int T=1;
        for(int t=0;t<T;t++){
            int n=Int(),k=Int();
            int A[][]=new int[n][2];
            for(int i=0;i<n;i++){
                A[i][0]=Int();
                A[i][1]=Int();
            }

            Solution sol=new Solution(out);
            sol.solution(A,k);
        }
        out.close();

    }

    public static int Int(){
        return fs.Int();
    }
    public static long Long(){
        return fs.Long();
    }
    public static String Str(){
        return fs.Str();
    }

}

class Solution{
    PrintWriter out;
    public Solution(PrintWriter out){
        this.out=out;
    }

    long dp[][];
    int mod=1000000007;
    int time;
    public void solution(int A[][],int t){
        this.time=t;
        dp=new long[4][1<<A.length+2];
        for(int i=0;i<dp.length;i++){
            Arrays.fill(dp[i],-1);
        }

        long a=dfs(A,0,(1<<A.length)-1);
        out.println(a);
    }

    public long dfs(int A[][],int pre,int state){
        int use=cal(A,state);
        if(time-use==0){
            return 1;
        }
        if(time<use||state==0){
            return 0;
        }

        if(dp[pre][state]!=-1)return dp[pre][state];

        long res=0;

        for(int i=0;i<A.length;i++){
            if(((state&(1<<i))!=0)&&A[i][1]!=pre){
                res+=dfs(A,A[i][1],(state^(1<<i)));
                res%=mod;
            }
        }

        dp[pre][state]=res;
        return res;
    }

    public int cal(int A[][],int state){
        int t=0;
        for(int i=0;i<A.length;i++){
            if((state&(1<<i))==0){
                t+=A[i][0];
            }
        }
        return t;
    }

}

/*
                             ;\
                            |' \
         _                  ; : ;
        / `-.              /: : |
       |  ,-.`-.          ,': : |
       \  :  `. `.       ,'-. : |
        \ ;    ;  `-.__,'    `-.|
         \ ;   ;  :::  ,::'`:.  `.
          \ `-. :  `    :.    `.  \
           \   \    ,   ;   ,:    (\
            \   :., :.    ,'o)): ` `-.
           ,/,' ;' ,::"'`.`---'   `.  `-._
         ,/  :  ; '"      `;'          ,--`.
        ;/   :; ;             ,:'     (   ,:)
          ,.,:.    ; ,:.,  ,-._ `.     \""'/
          '::'     `:'`  ,'(  \`._____.-'"'
             ;,   ;  `.  `. `._`-.  \\
             ;:.  ;:       `-._`-.\  \`.
              '`:. :        |' `. `\  ) \
      -hrr-      ` ;:       |    `--\__,'
                   '`      ,'
                        ,-'

                      free bug dog
*/


import java.io.*;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;

public class q5 {
	static NoD[] arr;
	static int index,count,zc;
	static ArrayList<NoD> pos,neg;
	static long[][][][] dp;

	static long solve(int a,int b, int c,int d, long mod) {
		long[][][][] a2=dp;
		int p=-1;
		if(a==0 && b==0 && c==0) return 1;
		if(dp[a][b][c][d]!=-1) return dp[a][b][c][d];
		long tr=0;
		if(a>0 && d!=1) {
			tr=+a*solve(a-1,b,c,1,mod);
			tr%=mod;
		}
		if(b >0 && d!=2) {
			tr+=b*solve(a,b-1,c,2,mod);
			tr%=mod;
		}
		if(c>0 && d!=3) {
			tr+=c*solve(a,b,c-1,3,mod);
			tr%=mod;
		}
		tr%=mod;
		return dp[a][b][c][d]=tr;

	}

	public static void main(String[] args) throws IOException {

		Reader.init(System.in);
		PrintWriter out=new PrintWriter(System.out);
		int n=Reader.nextInt(),t=Reader.nextInt();
		long mod=(long)1e9+7,fact[]=new long[16];
		dp=new long[16][16][16][4];
		for(int i=0;i<16;i++) {
			for(int j=0;j<16;j++) {
				for(int k=0;k<16;k++)
				Arrays.fill(dp[i][j][k], -1);
			}
		}
		fact[0]=1;
		for(int i=1;i<=15;i++) {
			fact[i]=i*fact[i-1];
			fact[i]%=mod;
		}
		NoD[] arr=new NoD[n];
		for(int i=0;i<n;i++) {
			int a=Reader.nextInt(),b=Reader.nextInt();
			arr[i]=new NoD(a,b);

		}
		long ans=0;
		for(int i=0;i<(1<<n);i++) {
			int time=0;
			int prev=-1;
			int t1=0,t2=0,t3=0;
			long[] c= {i};
			BitSet b=BitSet.valueOf(c);
			for(int j=0;j<n;j++) {
				if(b.get(j)) {
					time+=arr[j].val;
						prev=arr[j].index;
						if(arr[j].index==1) t1++;
						else if(arr[j].index==2) t2++;
						else t3++;
				}
			}
			if(time==t) {
				long v=1;
				long v2=1;
				v*=solve(t1,t2,t3,0,mod);
				v%=mod;
				ans+=v;
				ans%=mod;
			}
		}
		out.println(ans);
		out.flush();

	}
}

class NoD{
	int val, index;
	NoD(int v,int i){
		val=v;index=i;
	}
}

class Pair{
	NoD a, b;
	Pair(NoD aa,NoD bb){
		a=aa;b=bb;
	}
}

class Reader {
    static BufferedReader reader;
    static StringTokenizer tokenizer;
    /** call this method to initialize reader for InputStream */
    static void init(InputStream input) {
        reader = new BufferedReader(
                     new InputStreamReader(input) );
        tokenizer = new StringTokenizer("");
    }
    /** get next word */
    static String nextLine() throws IOException{
    	return reader.readLine();
    }
    static String next() throws IOException {
        while ( ! tokenizer.hasMoreTokens() ) {
            //TODO add check for eof if necessary
            tokenizer = new StringTokenizer(
                   reader.readLine() );
        }
        return tokenizer.nextToken();
    }
    static int nextInt() throws IOException {
        return Integer.parseInt( next() );
    }
    static long nextLong() throws IOException {
        return Long.parseLong( next() );
    }
    static double nextDouble() throws IOException {
        return Double.parseDouble( next() );
    }
}


import java.util.*;
public class G {
    static int n,t;
    static int[]a;
    static int[]g;
    static long[][][]dp;
    static final long MOD=1000000007;
    public static void main(String[]args){
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        t=sc.nextInt();
        a=new int[n];
        g=new int[n];
        for(int i=0;i<n;i++) {
            a[i] = sc.nextInt();
            g[i] = sc.nextInt();
        }
        dp=new long[4][1<<(n-1)+1][t+1];
        for(int i=0;i<4;i++)
            for(int j=0;j<1<<(n-1)+1;j++)
                for(int k=0;k<=t;k++)
                    dp[i][j][k]=-1;
        System.out.println(dp(0,0,t));
    }
    private static long dp(int genre,int mask,int time){
        if(time<0)
            return 0;
        if(dp[genre][mask][time]!=-1)
            return dp[genre][mask][time];
        if(time==0)
            return 1;
        dp[genre][mask][time]=0;
        for(int i=0;i<n;i++) {
            if (g[i] != genre && ((1 << i) & mask) == 0)
                dp[genre][mask][time] = (dp[genre][mask][time]+dp(g[i], mask | (1 << i), time - a[i]))%MOD;
        }
        return dp[genre][mask][time];
    }
}


import java.util.*;
import java.io.*;
import java.math.*;

/**
 *
 * @author Dstoical
 */

public class G {

	private static int M = 1000000007, MM = 998244353;
	private static int N = 15,n,T;
	private static int[] time,gi;
	private static int[][][] dp;

	public static void process() throws IOException {

		n = sc.nextInt();T = sc.nextInt();
		time = new int[n+1];
		gi = new int[n+1];
		for(int i=0; i<n; i++) {
			int a = sc.nextInt(),b = sc.nextInt();
			time[i] = a;
			gi[i] = b-1;
		}

		dp = new int[1<<n][T+1][3];
		for(int i=0; i<1<<n; i++) {
			for(int j=0; j<T+1; j++) {
				for(int k=0; k<3; k++)dp[i][j][k] = -1;
			}
		}

		int ans = 0;
		for(int i=0; i<n; i++) {
			if(time[i] <= T) {
				ans = (ans + solve(1<<i,time[i],gi[i]))%M;
			}
		}
		println(ans);
	}

	private static int solve(int mask, int tim, int code) {
		if(tim == T)return 1;
		if(dp[mask][tim][code] != -1)return dp[mask][tim][code];
		int ans = 0;
		for(int i=0; i<n; i++) {
			if((mask>>i & 1) > 0)continue;
			if(code == gi[i])continue;
			if(tim + time[i] > T)continue;
			ans = (ans + solve(mask|(1<<i), time[i]+tim, gi[i]))%M;

		}
		return dp[mask][tim][code] = (ans%M);
	}

	//=============================================================================
	//--------------------------The End---------------------------------
	//=============================================================================

	static FastScanner sc;
	static PrintWriter out;

	public static void main(String[] args) throws IOException {
		boolean oj = true;
		if (oj) {
			sc = new FastScanner();
			out = new PrintWriter(System.out);
		} else {
			sc = new FastScanner(100);
			out = new PrintWriter("output.txt");
		}
		int t = 1;
//		t = sc.nextInt();
		while (t-- > 0) {
			process();
		}
		out.flush();
		out.close();
	}

	static class Pair implements Comparable<Pair> {
		int x, y;

		Pair(int x, int y) {
			this.x = x;
			this.y = y;
		}

		@Override
		public int compareTo(Pair o) {
			return Integer.compare(this.x, o.x);
		}
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	static void println(Object o) {
		out.println(o);
	}

	static void println() {
		out.println();
	}

	static void print(Object o) {
		out.print(o);
	}

	static void pflush(Object o) {
		out.println(o);
		out.flush();
	}

	static int ceil(int x, int y) {
		return (x % y == 0 ? x / y : (x / y + 1));
	}

	static long ceil(long x, long y) {
		return (x % y == 0 ? x / y : (x / y + 1));
	}

	static int max(int x, int y) {
		return Math.max(x, y);
	}

	static int min(int x, int y) {
		return Math.min(x, y);
	}

	static int abs(int x) {
		return Math.abs(x);
	}

	static long abs(long x) {
		return Math.abs(x);
	}

	static int log2(int N) {
		int result = (int) (Math.log(N) / Math.log(2));
		return result;
	}

	static long max(long x, long y) {
		return Math.max(x, y);
	}

	static long min(long x, long y) {
		return Math.min(x, y);
	}

	public static int gcd(int a, int b) {
		BigInteger b1 = BigInteger.valueOf(a);
		BigInteger b2 = BigInteger.valueOf(b);
		BigInteger gcd = b1.gcd(b2);
		return gcd.intValue();
	}

	public static long gcd(long a, long b) {
		BigInteger b1 = BigInteger.valueOf(a);
		BigInteger b2 = BigInteger.valueOf(b);
		BigInteger gcd = b1.gcd(b2);
		return gcd.longValue();
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////

	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner() throws FileNotFoundException {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		FastScanner(int a) throws FileNotFoundException {
			br = new BufferedReader(new FileReader("input.txt"));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		String nextLine() throws IOException {
			String str = "";
			try {
				str = br.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return str;
		}

		int[] readArray(int n) throws IOException {
			int[] A = new int[n];
			for (int i = 0; i != n; i++) {
				A[i] = sc.nextInt();
			}
			return A;
		}

		long[] readArrayLong(int n) throws IOException {
			long[] A = new long[n];
			for (int i = 0; i != n; i++) {
				A[i] = sc.nextLong();
			}
			return A;
		}
	}

	static void ruffleSort(int[] a) {
		Random get = new Random();
		for (int i = 0; i < a.length; i++) {
			int r = get.nextInt(a.length);
			int temp = a[i];
			a[i] = a[r];
			a[r] = temp;
		}
		Arrays.sort(a);
	}

	static void ruffleSort(long[] a) {
		Random get = new Random();
		for (int i = 0; i < a.length; i++) {
			int r = get.nextInt(a.length);
			long temp = a[i];
			a[i] = a[r];
			a[r] = temp;
		}
		Arrays.sort(a);
	}
}


import java.util.*;
import java.lang.*;
import java.io.*;

public class Main
{
	static final int MOD = (int)1e9 + 7;
	static int n;
	static int[] t;
	static int[] g;
	static int[][] memo;

	static int dp(int mask, int rem, int last)
	{
		if(rem == 0)
			return 1;
		if(memo[last][mask] != -1)
			return memo[last][mask];

		int ans = 0;
		for(int i = 0; i < n; i++)
		{
			if((mask & (1 << i)) == 0 && rem >= t[i] && g[i] != last)
				ans += dp(mask | 1 << i, rem - t[i], g[i]);

			if(ans >= MOD)
				ans -= MOD;
		}

		return memo[last][mask] = ans;
	}

	public static void main (String[] args) throws java.lang.Exception
	{
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);

		n = in.nextInt();
		int T = in.nextInt();

		t = new int[n];
		g = new int[n];

		for(int i = 0; i < n; i++)
		{
			t[i] = in.nextInt();
			g[i] = in.nextInt() - 1;
		}

		memo = new int[4][1 << n];
		for(int []x : memo)
		{
			Arrays.fill(x, -1);
		}

		out.println(dp(0, T, 3));
		out.close();
	}

	static class InputReader
	{
		BufferedReader reader;
		StringTokenizer tokenizer;

		public InputReader(InputStream stream)
		{
			reader = new BufferedReader(new InputStreamReader(stream), 32768);
			tokenizer = null;
		}

		public String next()
		{
			while(tokenizer == null || !tokenizer.hasMoreTokens())
			{
				try
				{
					tokenizer = new StringTokenizer(reader.readLine());
				}
				catch(IOException e)
				{
					throw new RuntimeException(e);
				}
			}

			return tokenizer.nextToken();
		}

		public int nextInt()
		{
			return Integer.parseInt(next());
		}
	}
}


// https://codeforces.com/contest/1185/submission/55800229 (rainboy)
import java.io.*;
import java.util.*;

public class CF1185G2 {
	static final int MD = 1000000007;
	static int[][] solve1(int[] aa, int t, int n) {
		int[][] da = new int[t + 1][n + 1];
		da[0][0] = 1;
		for (int i = 0; i < n; i++) {
			int a = aa[i];
			for (int s = t - 1; s >= 0; s--)
				for (int m = 0; m < n; m++) {
					int x = da[s][m];
					if (x != 0) {
						int s_ = s + a;
						if (s_ <= t)
							da[s_][m + 1] = (da[s_][m + 1] + x) % MD;
					}
				}
		}
		return da;
	}
	static int[][][] solve2(int[] aa, int[] bb, int t, int na, int nb) {
		int[][] da = solve1(aa, t, na);
		int[][][] dab = new int[t + 1][na + 1][nb + 1];
		for (int s = 0; s <= t; s++)
			for (int ma = 0; ma <= na; ma++)
				dab[s][ma][0] = da[s][ma];
		for (int i = 0; i < nb; i++) {
			int b = bb[i];
			for (int s = t - 1; s >= 0; s--)
				for (int ma = 0; ma <= na; ma++)
					for (int mb = 0; mb < nb; mb++) {
						int x = dab[s][ma][mb];
						if (x != 0) {
							int s_ = s + b;
							if (s_ <= t)
								dab[s_][ma][mb + 1] = (dab[s_][ma][mb + 1] + x) % MD;
						}
					}
		}
		return dab;
	}
	static int[][][] init(int n, int na, int nb, int nc) {
		int[][][] dp = new int[na + 1][nb + 1][nc + 1];
		int[][][][] dq = new int[na + 1][nb + 1][nc + 1][3];
		for (int ma = 0; ma <= na; ma++)
			for (int mb = 0; mb <= nb; mb++)
				for (int mc = 0; mc <= nc; mc++)
					if (ma == 0 && mb == 0 && mc == 0) {
						dp[ma][mb][mc] = 1;
						dq[ma][mb][mc][0] = dq[ma][mb][mc][1] = dq[ma][mb][mc][2] = 1;
					} else {
						int x0 = ma > 0 ? (int) ((long) dq[ma - 1][mb][mc][0] * ma % MD) : 0;
						int x1 = mb > 0 ? (int) ((long) dq[ma][mb - 1][mc][1] * mb % MD) : 0;
						int x2 = mc > 0 ? (int) ((long) dq[ma][mb][mc - 1][2] * mc % MD) : 0;
						dp[ma][mb][mc] = (int) (((long) x0 + x1 + x2) % MD);
						dq[ma][mb][mc][0] = (x1 + x2) % MD;
						dq[ma][mb][mc][1] = (x2 + x0) % MD;
						dq[ma][mb][mc][2] = (x0 + x1) % MD;
					}
		return dp;
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int t = Integer.parseInt(st.nextToken());
		int[] aa = new int[n];
		int[] bb = new int[n];
		int[] cc = new int[n];
		int na = 0, nb = 0, nc = 0;
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());
			if (g == 1)
				aa[na++] = a;
			else if (g == 2)
				bb[nb++] = a;
			else
				cc[nc++] = a;
		}
		int[][][] dp = init(n, na, nb, nc);
		int[][][] dab = solve2(aa, bb, t, na, nb);
		int[][] dc = solve1(cc, t, nc);
		int ans = 0;
		for (int tab = 0; tab <= t; tab++) {
			int tc = t - tab;
			for (int ma = 0; ma <= na; ma++)
				for (int mb = 0; mb <= nb; mb++) {
					int xab = dab[tab][ma][mb];
					if (xab == 0)
						continue;
					for (int mc = 0; mc <= nc; mc++) {
						int xc = dc[tc][mc];
						if (xc == 0)
							continue;
						ans = (int) ((ans + (long) xab * xc % MD * dp[ma][mb][mc]) % MD);
					}
				}
		}
		System.out.println(ans);
	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Jeel Vaishnav
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        G1PlaylistForPolycarpEasyVersion solver = new G1PlaylistForPolycarpEasyVersion();
        solver.solve(1, in, out);
        out.close();
    }

    static class G1PlaylistForPolycarpEasyVersion {
        public void solve(int testNumber, InputReader sc, PrintWriter out) {
            int n = sc.nextInt();
            int T = sc.nextInt();

            int mod = (int) 1e9 + 7;

            int dp[][][] = new int[1 << n][226][3];

            int t[] = new int[n];
            int g[] = new int[n];
            for (int i = 0; i < n; ++i) {
                t[i] = sc.nextInt();
                g[i] = sc.nextInt() - 1;
                dp[1 << i][t[i]][g[i]] = 1;
            }

            for (int i = 0; i < (1 << n); ++i) {
                for (int j = 0; j < n; ++j) {
                    if ((i >> j & 1) == 1) {
                        int newMask = i ^ (1 << j);

                        for (int k = t[j]; k <= T; ++k) {
                            for (int l = 0; l < 3; ++l) {
                                if (l == g[j])
                                    continue;

                                dp[i][k][g[j]] = (dp[i][k][g[j]] + dp[newMask][k - t[j]][l]) % mod;
                            }
                        }
                    }
                }
            }

            long ans = 0;
            for (int i = 0; i < (1 << n); ++i) {
                for (int j = 0; j < 3; ++j) {
                    ans += dp[i][T][j];
                }
            }

            ans %= mod;
            out.print(ans);
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1)
                throw new InputMismatchException();

            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }

                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();

            while (isSpaceChar(c))
                c = read();

            int sgn = 1;

            if (c == '-') {
                sgn = -1;
                c = read();
            }

            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            while (!isSpaceChar(c));

            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


// Don't place your source in a package
import javax.swing.*;
import java.lang.reflect.Array;
import java.text.DecimalFormat;
import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.*;
import java.util.stream.Stream;

// Please name your class Main
public class Main {
    static FastScanner fs=new FastScanner();
    static class FastScanner {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer("");
        public String next() {
            while (!st.hasMoreElements())
                try {
                    st=new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return st.nextToken();
        }
        int Int() {
            return Integer.parseInt(next());
        }

        long Long() {
            return Long.parseLong(next());
        }

        String Str(){
            return next();
        }
    }

    public static void main (String[] args) throws java.lang.Exception {
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

        int T=1;
        for(int t=0;t<T;t++){
            int n=Int();
            int k=Int();
            int A[][]=new int[n][2];
            int a=0,b=0,c=0;
            for(int i=0;i<A.length;i++){
                A[i][0]=Int();
                A[i][1]=Int()-1;

                if(A[i][1]==0)a++;
                else if(A[i][1]==1)b++;
                else c++;
            }

            Arrays.sort(A,(x,y)->{
                return x[0]-y[0];
            });

            Solution sol=new Solution(out);
            sol.solution(A,k,a,b,c);
        }
        out.close();

    }

    public static int Int(){
        return fs.Int();
    }
    public static long Long(){
        return fs.Long();
    }
    public static String Str(){
        return fs.Str();
    }

}

class Solution{
    PrintWriter out;
    public Solution(PrintWriter out){
        this.out=out;
    }

    int mod=1000000007;
    long dp3[][][][];
    public void solution(int A[][],int T,int x,int y,int z){
        long res=0;
        int n=A.length;
        long dp1[][]=new long[x+2][T+1];//a
        long dp2[][][]=new long[y+2][z+2][T+2];//bc
        dp3=new long[x+2][y+2][z+2][3];

        //init
        long f[]=new long[n+10];
        f[0]=f[1]=1;
        for(int i=2;i<f.length;i++){
            f[i]=f[i-1]*i;
            f[i]%=mod;
        }
        for(int i=0;i<dp3.length;i++){
            for(int j=0;j<dp3[0].length;j++){
                for(int k=0;k<dp3[0][0].length;k++){
                    Arrays.fill(dp3[i][j][k],-1);
                }
            }
        }

        dp1[0][0]=1;
        for(int i=0;i<A.length;i++){//a
            int p=A[i][0],type=A[i][1];
            if(type==0){
                long newdp[][]=new long[dp1.length][dp1[0].length];
                for(int cnt=1;cnt<=x;cnt++){
                    for(int j=1;j<dp1[0].length;j++){
                        if(j>=p){
                            newdp[cnt][j]+=dp1[cnt-1][j-p];
                            newdp[cnt][j]%=mod;
                        }
                    }
                }

                for(int cnt=0;cnt<=x;cnt++){
                    for(int j=0;j<dp1[0].length;j++){
                        newdp[cnt][j]+=dp1[cnt][j];
                        newdp[cnt][j]%=mod;
                    }
                }
                dp1=newdp;
            }
        }

        dp2[0][0][0]=1;
        for(int i=0;i<A.length;i++){//b c
            int p=A[i][0],type=A[i][1];
            if(type!=0){
                long newdp[][][]=new long[dp2.length][dp2[0].length][dp2[0][0].length];
                for(int a=0;a<dp2.length;a++){
                    for(int b=0;b<dp2[0].length;b++){
                        for(int j=0;j<dp2[0][0].length;j++){
                            if(j>=p){
                                if(type==1){
                                    if(a-1>=0){
                                        newdp[a][b][j]+=dp2[a-1][b][j-p];
                                    }
                                }
                                else{
                                    if(b-1>=0) {
                                        newdp[a][b][j]+=dp2[a][b-1][j-p];
                                    }
                                }
                            }
                            newdp[a][b][j]%=mod;
                        }
                    }
                }

                for(int a=0;a<dp2.length;a++){
                    for(int b=0;b<dp2[0].length;b++){
                        for(int j=0;j<dp2[0][0].length;j++){
                            newdp[a][b][j]+=dp2[a][b][j];
                            newdp[a][b][j]%=mod;
                        }
                    }
                }
                dp2=newdp;
            }
        }

        dp3[1][0][0][0]=1;
        dp3[0][1][0][1]=1;
        dp3[0][0][1][2]=1;
        for(int i=0;i<dp3.length;i++){
            for(int j=0;j<dp3[0].length;j++){
                for(int k=0;k<dp3[0][0].length;k++){
                    for(x=0;x<dp3[0][0][0].length;x++){
                        if(dp3[i][j][k][x]==-1){
                            dfs(i,j,k,x);
                        }
                    }
                }
            }
        }

        for(int i=0;i<dp3.length;i++){
            for(int j=0;j<dp3[0].length;j++){
                for(int k=0;k<dp3[0][0].length;k++){
                    for(int cur=0;cur<3;cur++){
                        for(int t=0;t<=T;t++){//price
                            int aprice=t;
                            int bcprice=T-t;
                            long cnt1=dp1[i][aprice];
                            long cnt2=dp2[j][k][bcprice];
                            long combination=dp3[i][j][k][cur];
                            ///if(combination==-1)combination=0;
                            long p1=(cnt1*f[i])%mod;
                            long p2=(((f[j]*f[k])%mod)*cnt2)%mod;
                            long p3=(p1*p2)%mod;
                            res+=(p3*combination)%mod;
                            res%=mod;

                        }
                    }
                }
            }
        }

        //System.out.println(dp2[1][0][2]+"   "+dp3[1][1][0][0]);

       // for(long p[]:dp1){
           // System.out.println(Arrays.toString(p));
        //}

        out.println(res);

    }

    public long dfs(int a,int b,int c,int cur){
        if(a<0||b<0||c<0){
            return 0;
        }
        if(a==0&&b==0&&c==0){
            return 0;
        }

        if(dp3[a][b][c][cur]!=-1)return dp3[a][b][c][cur];

        long res=0;
        if(cur==0){
            res+=dfs(a-1,b,c,1);
            res%=mod;
            res+=dfs(a-1,b,c,2);
            res%=mod;

        }
        else if(cur==1){
            res+=dfs(a,b-1,c,0);
            res%=mod;
            res+=dfs(a,b-1,c,2);
            res%=mod;
        }
        else{
            res+=dfs(a,b,c-1,0);
            res%=mod;
            res+=dfs(a,b,c-1,1);
            res%=mod;
        }
        res%=mod;
        dp3[a][b][c][cur]=res;
        return res;
    }

}

/*
                             ;\
                            |' \
         _                  ; : ;
        / `-.              /: : |
       |  ,-.`-.          ,': : |
       \  :  `. `.       ,'-. : |
        \ ;    ;  `-.__,'    `-.|
         \ ;   ;  :::  ,::'`:.  `.
          \ `-. :  `    :.    `.  \
           \   \    ,   ;   ,:    (\
            \   :., :.    ,'o)): ` `-.
           ,/,' ;' ,::"'`.`---'   `.  `-._
         ,/  :  ; '"      `;'          ,--`.
        ;/   :; ;             ,:'     (   ,:)
          ,.,:.    ; ,:.,  ,-._ `.     \""'/
          '::'     `:'`  ,'(  \`._____.-'"'
             ;,   ;  `.  `. `._`-.  \\
             ;:.  ;:       `-._`-.\  \`.
              '`:. :        |' `. `\  ) \
      -hrr-      ` ;:       |    `--\__,'
                   '`      ,'
                        ,-'

                      free bug dog
*/

/*
5 3
1 1
2 1
2 1
2 1
2 2
 */


import java.io.*;
import java.util.*;
import java.math.BigInteger;
import java.util.Map.Entry;

import static java.lang.Math.*;

public class G extends PrintWriter {

    void run() {
        long mod = 1_000_000_000 + 7;
        int n = nextInt();
        int m = nextInt();

        int[] t = new int[n];
        int[] g = new int[n];

        for (int i = 0; i < n; i++) {
            t[i] = nextInt();
            g[i] = nextInt() - 1;
        }

        int k = 1 << n;

        long[][] dp = new long[k][n];

        for (int i = 0; i < n; i++) {
            dp[1 << i][i] = 1;
        }

        for (int mask = 0; mask < k; mask++) {
            if (Integer.bitCount(mask) <= 1) {
                continue;
            }

            for (int i = 0; i < n; i++) {
                if ((mask & (1 << i)) != 0) {
                    for (int j = 0; j < n; j++) {
                        if ((mask & (1 << j)) == 0 || g[i] == g[j]) {
                            continue;
                        }
                        dp[mask][i] = (dp[mask][i] + dp[mask ^ (1 << i)][j]) % mod;
                    }
                }
            }
        }

        long ans = 0;
        for (int mask = 0; mask < k; mask++) {
            int sum = 0;
            for (int i = 0; i < n; i++) {
                if ((mask & (1 << i)) != 0) {
                    sum += t[i];
                }
            }
            if (sum == m) {

                for (int i = 0; i < n; i++) {
                    if ((mask & (1 << i)) != 0) {
                        ans = (ans + dp[mask][i]) % mod;
                    }
                }

            }

        }

        println(ans);

    }

    boolean skip() {
        while (hasNext()) {
            next();
        }
        return true;
    }

    int[][] nextMatrix(int n, int m) {
        int[][] matrix = new int[n][m];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                matrix[i][j] = nextInt();
        return matrix;
    }

    String next() {
        while (!tokenizer.hasMoreTokens())
            tokenizer = new StringTokenizer(nextLine());
        return tokenizer.nextToken();
    }

    boolean hasNext() {
        while (!tokenizer.hasMoreTokens()) {
            String line = nextLine();
            if (line == null) {
                return false;
            }
            tokenizer = new StringTokenizer(line);
        }
        return true;
    }

    int[] nextArray(int n) {
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = nextInt();
        }
        return array;
    }

    long[] nextLongArray(int n) {
        long[] array = new long[n];
        for (int i = 0; i < n; i++) {
            array[i] = nextLong();
        }
        return array;
    }

    int nextInt() {
        return Integer.parseInt(next());
    }

    long nextLong() {
        return Long.parseLong(next());
    }

    double nextDouble() {
        return Double.parseDouble(next());
    }

    String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException err) {
            return null;
        }
    }

    public G(OutputStream outputStream) {
        super(outputStream);
    }

    static BufferedReader reader;
    static StringTokenizer tokenizer = new StringTokenizer("");
    static Random rnd = new Random();
    static boolean OJ;

    public static void main(String[] args) throws IOException {
        OJ = System.getProperty("ONLINE_JUDGE") != null;
        G solution = new G(System.out);
        if (OJ) {
            reader = new BufferedReader(new InputStreamReader(System.in));
            solution.run();
        } else {
            reader = new BufferedReader(new FileReader(new File(G.class.getName() + ".txt")));
            long timeout = System.currentTimeMillis();
            while (solution.hasNext()) {
                solution.run();
                solution.println();
                solution.println("----------------------------------");
            }
            solution.println("time: " + (System.currentTimeMillis() - timeout));
        }
        solution.close();
        reader.close();
    }
}


import java.io.IOException;
import java.io.InputStream;
import java.util.NoSuchElementException;

public class Main {
    private static FastScanner sc = new FastScanner();
    private static long mod = 1000000007;

    public static void main(String[] args) {
    	int n = sc.nextInt();
    	int T = sc.nextInt();
    	int[] t = new int[n];
    	int[] g = new int[n];
    	for(int i=0; i<n; i++) {
    		t[i] = sc.nextInt();
    		g[i] = sc.nextInt() - 1;
    	}
    	long[][][] dp = new long[T+1][3][1 << 15];
    	for(int i=1; i<=T; i++) {
    		for(int j=0; j<n; j++) {
    			if(i - t[j] == 0) {
    				dp[i][g[j]][1 << j] = (dp[i][g[j]][1 << j] + 1) % mod;
    			} else if(i - t[j] > 0) {
    				for(int k=0; k<(1 << 15); k++) {
    					if((k >> j & 1) == 1) {
    						continue;
    					}
    					dp[i][g[j]][k + (1 << j)] = (dp[i][g[j]][k + (1 << j)] + dp[i - t[j]][(g[j] + 1) % 3][k] + dp[i - t[j]][(g[j] + 2) % 3][k]) % mod;
    				}
    			}
    		}
    	}
    	long ans = 0;
    	for(int j=0; j<3; j++) {
    		for(int k=0; k<(1 << 15); k++) {
    			ans = (ans + dp[T][j][k]) % mod;
    		}
    	}
    	System.out.println(ans);
    }

    static long power(long m , long n){
    	if(n == 0) {
    		return 1;
    	}else if(n == 1){
            return m;
        }else if(n % 2 == 0){
            long s = power(m, n/2);
            return ( (s % mod) * (s % mod) ) % mod;
        }else{
            return ( (m % mod) * (power(m, n-1) % mod) ) % mod;
        }
    }

    static class FastScanner {
        private final InputStream in = System.in;
        private final byte[] buffer = new byte[1024];
        private int ptr = 0;
        private int buflen = 0;
        private boolean hasNextByte() {
            if(ptr < buflen) {
                return true;
            } else {
                ptr = 0;
                try {
                    buflen = in.read(buffer);
                } catch(IOException e) {
                    e.printStackTrace();
                }
                if(buflen <= 0) {
                    return false;
                }
            }
            return true;
        }
        private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
        private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
        private void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
        public boolean hasNext() { skipUnprintable(); return hasNextByte();}
        public String next() {
            if (!hasNext()) throw new NoSuchElementException();
            StringBuilder sb = new StringBuilder();
            int b = readByte();
            while(isPrintableChar(b)) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public int nextInt(){
            return Integer.parseInt(next());
        }
        public double nextDouble(){
            return Double.parseDouble(next());
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Vaibhav Pulastya
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        G1PlaylistForPolycarpEasyVersion solver = new G1PlaylistForPolycarpEasyVersion();
        solver.solve(1, in, out);
        out.close();
    }

    static class G1PlaylistForPolycarpEasyVersion {
        long mod = (int) 1e9 + 7;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int T = in.nextInt();
            int[] t = new int[n];
            int[] g = new int[n];
            for (int i = 0; i < n; i++) {
                t[i] = in.nextInt();
                g[i] = in.nextInt();
            }
            long[] fact = new long[n + 1];
            fact[0] = 1;
            for (int i = 1; i <= n; i++) {
                fact[i] = (fact[i - 1] * i) % mod;
            }
            ArrayList<Integer> masks = new ArrayList<>();
            long val = 0;
            for (int i = 1; i < (1 << n); i++) {
                int time = 0;
                int[] count = new int[3];
                for (int j = 0; j < n; j++) {
                    if ((i & (1 << j)) != 0) {
                        time += t[j];
                        count[g[j] - 1]++;
                    }
                }
                if (time == T) {
                    masks.add(i);
                    Arrays.sort(count);
                    long v = ((fact[count[0]] * fact[count[1]]) % mod * fact[count[2]]) % mod;
                    val += ((countUtil(count[0], count[1], count[2])) * v) % mod;
                }
            }
            out.println(val%mod);

        }

        long countWays(int p, int q, int r, int last) {
            // if number of balls of any
            // color becomes less than 0
            // the number of ways arrangements is 0.
            if (p < 0 || q < 0 || r < 0)
                return 0;

            // If last ball required is
            // of type P and the number
            // of balls of P type is 1
            // while number of balls of
            // other color is 0 the number
            // of ways is 1.
            if (p == 1 && q == 0 && r == 0 && last == 0)
                return 1;

            // Same case as above for 'q' and 'r'
            if (p == 0 && q == 1 && r == 0 && last == 1)
                return 1;
            if (p == 0 && q == 0 && r == 1 && last == 2)
                return 1;

            // if last ball required is P
            // and the number of ways is
            // the sum of number of ways
            // to form sequence with 'p-1' P
            // balls, q Q Balls and r R balls
            // ending with Q and R.
            if (last == 0)
                return (countWays(p - 1, q, r, 1) +
                        countWays(p - 1, q, r, 2)) % mod;

            // Same as above case for 'q' and 'r'
            if (last == 1)
                return (countWays(p, q - 1, r, 0) +
                        countWays(p, q - 1, r, 2)) % mod;

            if (last == 2)
                return (countWays(p, q, r - 1, 0) +
                        countWays(p, q, r - 1, 1)) % mod;

            return 0;
        }

        long countUtil(int p, int q, int r) {
            // Three cases arise:
            return ((countWays(p, q, r, 0) +
                    countWays(p, q, r, 1)) % mod +
                    countWays(p, q, r, 2)) % mod;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1)
                throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //   npe, particularly in maps
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int[] nT = ril(2);
        int n = nT[0];
        int T = nT[1];
        int[][] tg = new int[n][];
        for (int i = 0; i < n; i++) tg[i] = ril(2);

        // dp[t][m][g] is the number of sequences possible to be formed from
        // songs indicated by mask m, having total time t, and whose last song
        // is genre g.
        int[][][] dp = new int[T+1][1 << n][3];
        for (int ti = 1; ti <= T; ti++) {
            for (int mask = 1; mask <= (1 << n); mask++) {
                // Iterate over the possible last song. It's genre will determine
                // what the third dimension should be
                for (int j = 0; j < n; j++) {
                    if (((1 << j) & mask) == 0) continue;
                    int time = tg[j][0];
                    int genre = tg[j][1]-1;
                    if (ti - time < 0) continue;
                    long base = dp[ti][mask][genre];
                    long add = 0;
                    if (ti - time == 0) {
                        // Base case: there is always one way regardless of what songs are available.
                        // The empty playlist
                        add = 1;
                    } else {
                        for (int g = 0; g < 3; g++) add += dp[ti-time][mask ^ (1 << j)][g];
                        add -= dp[ti-time][mask ^ (1 << j)][genre];
                    }
                    dp[ti][mask][genre] = (int) ((base + add) % MOD);
                }
            }
        }
        long ans = 0;
        for (int g = 0; g < 3; g++) ans += dp[T][(1 << n)-1][g];
        pw.println(ans % MOD);
    }
    // IMPORTANT
    // DID YOU CHECK THE COMMON MISTAKES ABOVE?

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.util.Arrays;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.TreeSet;

public class r568p8{

    private static InputReader sc;
    private static PrintWriter pw;
    private static long mod;

    static class InputReader {
        private final InputStream stream;
        private final byte[] buf = new byte[8192];
        private int curChar, snumChars;
        private SpaceCharFilter filter;

        InputReader(InputStream stream) {
            this.stream = stream;
        }

        int snext() {
            if (snumChars == -1)
                throw new InputMismatchException();
            if (curChar >= snumChars) {
                curChar = 0;
                try {
                    snumChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (snumChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        int nextInt() {
            int c = snext();
            while (isSpaceChar(c)) {
                c = snext();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = snext();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = snext();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        long nextLong() {
            int c = snext();
            while (isSpaceChar(c)) {
                c = snext();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = snext();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = snext();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        String readString() {
            int c = snext();
            while (isSpaceChar(c)) {
                c = snext();
            }
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = snext();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        String nextLine() {
            int c = snext();
            while (isSpaceChar(c))
                c = snext();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = snext();
            } while (!isEndOfLine(c));
            return res.toString();
        }

        boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public interface SpaceCharFilter {
            boolean isSpaceChar(int ch);
        }
    }

    public static void main(String args[]) {
        sc = new InputReader(System.in);
        pw = new PrintWriter(System.out);

        int t = 1;
        while(t-->0)
            solve();

        pw.flush();
        pw.close();
    }

    private static void fill_matrix(long dp[][][][], int a, int b, int c, int end){

        if((a == 0 && b == 0 && c == 0) || (a == 0 && end == 0) || (b == 0 && end == 1) || (c == 0 && end == 2)){
            dp[a][b][c][end] = 0;
            return;
        }

        if(a > 1 && b == 0 && c == 0){
            dp[a][b][c][end] = 0;
            return;
        }

        if(b > 1 && a == 0 && c == 0){
            dp[a][b][c][end] = 0;
            return;
        }

        if(c > 1 && a == 0 && b == 0){
            dp[a][b][c][end] = 0;
            return;
        }

        if(a == 1 && end == 0 && b == 0 && c == 0){
            dp[a][b][c][end] = 1;
            return;
        }
        if(b == 1 && end == 1 && a == 0 && c == 0){
            dp[a][b][c][end] = 1;
            return;
        }
        if(c == 1 && end == 2 && b == 0 && a == 0){
            dp[a][b][c][end] = 1;
            return;
        }

        if(end == 0){
            fill_matrix(dp, a-1, b, c, 1);
            fill_matrix(dp, a-1, b, c, 2);

            dp[a][b][c][0] = (dp[a-1][b][c][1]%mod + dp[a-1][b][c][2]%mod)%mod;
        }
        else if(end == 1){
            fill_matrix(dp, a, b-1, c, 0);
            fill_matrix(dp, a, b-1, c, 2);

            dp[a][b][c][1] = (dp[a][b-1][c][0]%mod + dp[a][b-1][c][2]%mod)%mod;
        }
        else{
            fill_matrix(dp, a, b, c-1, 0);
            fill_matrix(dp, a, b, c-1, 1);

            dp[a][b][c][2] = (dp[a][b][c-1][0]%mod + dp[a][b][c-1][1]%mod)%mod;
        }
    }

    private static long cal(int count[]){
        int a = count[0], b = count[1], c = count[2];
        long dp[][][][] = new long[a+1][b+1][c+1][3];

        long factorial[] = new long[20];

        factorial[0] = 1;
        factorial[1] = 1;

        for(int i=2; i<20; i++)
            factorial[i] = (factorial[i-1]%mod*i%mod)%mod;

        fill_matrix(dp, a, b, c, 0);
        fill_matrix(dp, a, b, c, 1);
        fill_matrix(dp, a, b, c, 2);

         long p = (dp[a][b][c][0]%mod + dp[a][b][c][1]%mod + dp[a][b][c][2]%mod)%mod;

         long ans = (((p%mod * factorial[a]%mod)%mod * factorial[b]%mod)%mod * factorial[c]%mod)%mod;

         return ans;
    }

    private static void solve(){
        int n = sc.nextInt(), T = sc.nextInt();

        int len[] = new int[n], genre[] = new int[n];

        for(int i=0; i<n; i++){
            len[i] = sc.nextInt();
            genre[i] = sc.nextInt();
        }

        int sum[] = new int[(1<<n)];

        mod = (long)1e9 + 7;
        long ans = 0;

        for(int i=1; i<(1<<n); i++){
            for(int j=0; j<15; j++){
                if((i&(1<<j)) != 0){
                    sum[i] = sum[i^(1<<j)] + len[j];
                    break;
                }
            }

            if(sum[i] == T) {
                int count[] = {0, 0, 0};

                for (int j = 0; j < 15; j++) {
                    if ((i & (1 << j)) != 0)
                        count[genre[j] - 1]++;
                }

                ans = (ans % mod + cal(count) % mod) % mod;
            }
        }

        pw.println(+ans);
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.FilterInputStream;
import java.io.BufferedInputStream;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author khokharnikunj8
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        ScanReader in = new ScanReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        G1playlist solver = new G1playlist();
        solver.solve(1, in, out);
        out.close();
    }

    static class G1playlist {
        int mod = 1000000007;

        public void solve(int testNumber, ScanReader in, PrintWriter out) {
            int n = in.scanInt();
            int T = in.scanInt();
            int[][] song = new int[n][2];
            for (int i = 0; i < n; i++) {
                song[i][0] = in.scanInt();
                song[i][1] = in.scanInt() - 1;
            }
            int[][][] dp = new int[T + 1][(1 << n)][3];
            for (int i = 0; i < n; i++)
                if (song[i][0] <= T) {
                    dp[song[i][0]][(1 << i)][song[i][1]] = 1;
                }
            for (int t = 0; t <= T; t++) {
                for (int i = 0; i < (1 << n); i++) {
                    for (int j = 0; j < 3; j++) {
                        if (dp[t][i][j] == 0) continue;
                        for (int k = 0; k < n; k++) {
                            if (((1 << k) & i) == 0 && t + song[k][0] <= T && song[k][1] != j)
                                dp[t + song[k][0]][(1 << k) | i][song[k][1]] = (dp[t + song[k][0]][(1 << k) | i][song[k][1]] + dp[t][i][j]) % mod;
                        }
                    }
                }
            }
            long ans = 0;
            for (int i = 0; i < (1 << n); i++) {
                for (int j = 0; j < 3; j++) {
                    ans = (ans + dp[T][i][j]) % mod;
                }
            }
            out.println(ans);
        }

    }

    static class ScanReader {
        private byte[] buf = new byte[4 * 1024];
        private int index;
        private BufferedInputStream in;
        private int total;

        public ScanReader(InputStream inputStream) {
            in = new BufferedInputStream(inputStream);
        }

        private int scan() {
            if (index >= total) {
                index = 0;
                try {
                    total = in.read(buf);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (total <= 0) return -1;
            }
            return buf[index++];
        }

        public int scanInt() {
            int integer = 0;
            int n = scan();
            while (isWhiteSpace(n)) n = scan();
            int neg = 1;
            if (n == '-') {
                neg = -1;
                n = scan();
            }
            while (!isWhiteSpace(n)) {
                if (n >= '0' && n <= '9') {
                    integer *= 10;
                    integer += n - '0';
                    n = scan();
                }
            }
            return neg * integer;
        }

        private boolean isWhiteSpace(int n) {
            if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
            else return false;
        }

    }
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class cf1185g1_3 {

    public static void main(String[] args) throws IOException {
        int n = rni(), t = ni(), song[][] = new int[n][2];
        for (int i = 0; i < n; ++i) {
            song[i][0] = rni();
            song[i][1] = ni() - 1;
        }
        int dp[][] = new int[1 << n][4], sum[] = new int[1 << n], ans = 0;
        dp[0][3] = 1;
        for (int i = 0; i < 1 << n; ++i) {
            for (int j = 0; j < 4; ++j) {
                for (int k = 0; k < n; ++k) {
                    if ((i & (1 << k)) == 0 && song[k][1] != j) {
                        dp[i | (1 << k)][song[k][1]] = madd(dp[i | (1 << k)][song[k][1]], dp[i][j]);
                        sum[i | (1 << k)] = sum[i] + song[k][0];
                    }
                }
            }
        }
        for (int i = 0; i < 1 << n; ++i) {
            if (sum[i] == t) {
                ans = madd(ans, dp[i][0], dp[i][1], dp[i][2]);
            }
        }
        prln(ans);
        close();
    }

    static int mmod = 1000000007;

    static int madd(int a, int b) {
        return (a + b) % mmod;
    }

    static int madd(int... a) {
        int ans = a[0];
        for (int i = 1; i < a.length; ++i) {
            ans = madd(ans, a[i]);
        }
        return ans;
    }

    static int msub(int a, int b) {
        return (a - b + mmod) % mmod;
    }

    static int mmul(int a, int b) {
        return (int) ((long) a * b % mmod);
    }

    static int mmul(int... a) {
        int ans = a[0];
        for (int i = 1; i < a.length; ++i) {
            ans = mmul(ans, a[i]);
        }
        return ans;
    }

    static int minv(int x) {
        // return mpow(x, mmod - 2);
        return (exgcd(x, mmod)[0] % mmod + mmod) % mmod;
    }

    static int mpow(int a, long b) {
        if (a == 0) {
            return 0;
        }
        int ans = 1;
        while (b > 0) {
            if ((b & 1) > 0) {
                ans = mmul(ans, a);
            }
            a = mmul(a, a);
            b >>= 1;
        }
        return ans;
    }

    static BufferedReader __i = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter __o = new PrintWriter(new OutputStreamWriter(System.out));
    static StringTokenizer input;
    static Random __r = new Random();

    // references
    // IBIG = 1e9 + 7
    // IMAX ~= 2e9
    // LMAX ~= 9e18

    // constants
    static final int IBIG = 1000000007;
    static final int IMAX = 2147483647;
    static final long LMAX = 9223372036854775807L;
    // math util
    static int minof(int a, int b, int c) {return min(a, min(b, c));}
    static int minof(int... x) {if (x.length == 1) return x[0]; if (x.length == 2) return min(x[0], x[1]); if (x.length == 3) return min(x[0], min(x[1], x[2])); int min = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] < min) min = x[i]; return min;}
    static long minof(long a, long b, long c) {return min(a, min(b, c));}
    static long minof(long... x) {if (x.length == 1) return x[0]; if (x.length == 2) return min(x[0], x[1]); if (x.length == 3) return min(x[0], min(x[1], x[2])); long min = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] < min) min = x[i]; return min;}
    static int maxof(int a, int b, int c) {return max(a, max(b, c));}
    static int maxof(int... x) {if (x.length == 1) return x[0]; if (x.length == 2) return max(x[0], x[1]); if (x.length == 3) return max(x[0], max(x[1], x[2])); int max = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] > max) max = x[i]; return max;}
    static long maxof(long a, long b, long c) {return max(a, max(b, c));}
    static long maxof(long... x) {if (x.length == 1) return x[0]; if (x.length == 2) return max(x[0], x[1]); if (x.length == 3) return max(x[0], max(x[1], x[2])); long max = x[0]; for (int i = 1; i < x.length; ++i) if (x[i] > max) max = x[i]; return max;}
    static int powi(int a, int b) {if (a == 0) return 0; int ans = 1; while (b > 0) {if ((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static long powl(long a, int b) {if (a == 0) return 0; long ans = 1; while (b > 0) {if ((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static int fli(double d) {return (int) d;}
    static int cei(double d) {return (int) ceil(d);}
    static long fll(double d) {return (long) d;}
    static long cel(double d) {return (long) ceil(d);}
    static int gcf(int a, int b) {return b == 0 ? a : gcf(b, a % b);}
    static long gcf(long a, long b) {return b == 0 ? a : gcf(b, a % b);}
    static int[] exgcd(int a, int b) {if (b == 0) return new int[] {1, 0}; int[] y = exgcd(b, a % b); return new int[] {y[1], y[0] - y[1] * (a / b)};}
    static long[] exgcd(long a, long b) {if (b == 0) return new long[] {1, 0}; long[] y = exgcd(b, a % b); return new long[] {y[1], y[0] - y[1] * (a / b)};}
    static int randInt(int min, int max) {return __r.nextInt(max - min + 1) + min;}
    static long mix(long x) {x += 0x9e3779b97f4a7c15L; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9L; x = (x ^ (x >> 27)) * 0x94d049bb133111ebL; return x ^ (x >> 31);}
    // array util
    static void reverse(int[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {int swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(long[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {long swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(double[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {double swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(char[] a) {for (int i = 0, n = a.length, half = n / 2; i < half; ++i) {char swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void shuffle(int[] a) {int n = a.length - 1; for (int i = 0; i < n; ++i) {int ind = randInt(i, n); int swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(long[] a) {int n = a.length - 1; for (int i = 0; i < n; ++i) {int ind = randInt(i, n); long swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(double[] a) {int n = a.length - 1; for (int i = 0; i < n; ++i) {int ind = randInt(i, n); double swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void rsort(int[] a) {shuffle(a); sort(a);}
    static void rsort(long[] a) {shuffle(a); sort(a);}
    static void rsort(double[] a) {shuffle(a); sort(a);}
    static int[] copy(int[] a) {int[] ans = new int[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static long[] copy(long[] a) {long[] ans = new long[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static double[] copy(double[] a) {double[] ans = new double[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static char[] copy(char[] a) {char[] ans = new char[a.length]; for (int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    // input
    static void r() throws IOException {input = new StringTokenizer(rline());}
    static int ri() throws IOException {return Integer.parseInt(rline());}
    static long rl() throws IOException {return Long.parseLong(rline());}
    static double rd() throws IOException {return Double.parseDouble(rline());}
    static int[] ria(int n) throws IOException {int[] a = new int[n]; r(); for (int i = 0; i < n; ++i) a[i] = ni(); return a;}
    static int[] riam1(int n) throws IOException {int[] a = new int[n]; r(); for (int i = 0; i < n; ++i) a[i] = ni() - 1; return a;}
    static long[] rla(int n) throws IOException {long[] a = new long[n]; r(); for (int i = 0; i < n; ++i) a[i] = nl(); return a;}
    static double[] rda(int n) throws IOException {double[] a = new double[n]; r(); for (int i = 0; i < n; ++i) a[i] = nd(); return a;}
    static char[] rcha() throws IOException {return rline().toCharArray();}
    static String rline() throws IOException {return __i.readLine();}
    static String n() {return input.nextToken();}
    static int rni() throws IOException {r(); return ni();}
    static int ni() {return Integer.parseInt(n());}
    static long rnl() throws IOException {r(); return nl();}
    static long nl() {return Long.parseLong(n());}
    static double rnd() throws IOException {r(); return nd();}
    static double nd() {return Double.parseDouble(n());}
    // output
    static void pr(int i) {__o.print(i);}
    static void prln(int i) {__o.println(i);}
    static void pr(long l) {__o.print(l);}
    static void prln(long l) {__o.println(l);}
    static void pr(double d) {__o.print(d);}
    static void prln(double d) {__o.println(d);}
    static void pr(char c) {__o.print(c);}
    static void prln(char c) {__o.println(c);}
    static void pr(char[] s) {__o.print(new String(s));}
    static void prln(char[] s) {__o.println(new String(s));}
    static void pr(String s) {__o.print(s);}
    static void prln(String s) {__o.println(s);}
    static void pr(Object o) {__o.print(o);}
    static void prln(Object o) {__o.println(o);}
    static void prln() {__o.println();}
    static void pryes() {prln("yes");}
    static void pry() {prln("Yes");}
    static void prY() {prln("YES");}
    static void prno() {prln("no");}
    static void prn() {prln("No");}
    static void prN() {prln("NO");}
    static boolean pryesno(boolean b) {prln(b ? "yes" : "no"); return b;};
    static boolean pryn(boolean b) {prln(b ? "Yes" : "No"); return b;}
    static boolean prYN(boolean b) {prln(b ? "YES" : "NO"); return b;}
    static void prln(int... a) {for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i); if (a.length > 0) prln(a[a.length - 1]); else prln();}
    static void prln(long... a) {for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i); if (a.length > 0) prln(a[a.length - 1]); else prln();}
    static void prln(double... a) {for (int i = 0, len = a.length - 1; i < len; pr(a[i]), pr(' '), ++i); if (a.length > 0) prln(a[a.length - 1]); else prln();}
    static <T> void prln(Collection<T> c) {int n = c.size() - 1; Iterator<T> iter = c.iterator(); for (int i = 0; i < n; pr(iter.next()), pr(' '), ++i); if (n >= 0) prln(iter.next()); else prln();}
    static void h() {prln("hlfd"); flush();}
    static void flush() {__o.flush();}
    static void close() {__o.close();}
}


import java.io.*;
import java.util.*;

public class B {

	static int n,t[],g[],MOD=(int)1e9+7;
	static int [][]memo;
	static int dp(int msk,int rem,int lastG) {
		if(rem==0)
			return 1;
		if(memo[lastG][msk]!=-1)
			return memo[lastG][msk];
		int ans=0;
		for(int i=0;i<n;i++) {
			if((msk & (1<<i))==0 && rem>=t[i] && g[i]!=lastG)
				ans+=dp(msk|1<<i,rem-t[i],g[i]);
				if(ans>=MOD)
					ans-=MOD;
		}
		return memo[lastG][msk]=ans;
	}
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n=sc.nextInt();
		int T=sc.nextInt();
		t=new int [n];
		g=new int [n];

		for(int i=0;i<n;i++) {
			t[i]=sc.nextInt();
			g[i]=sc.nextInt()-1;
		}
		memo=new int [4][1<<n];
		for(int []x:memo)
			Arrays.fill(x, -1);
		out.println(dp(0, T, 3));
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

		Scanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		Scanner(String fileName) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(fileName));
		}

		String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		String nextLine() throws IOException {
			return br.readLine();
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		long nextLong() throws NumberFormatException, IOException {
			return Long.parseLong(next());
		}

		double nextDouble() throws NumberFormatException, IOException {
			return Double.parseDouble(next());
		}

		boolean ready() throws IOException {
			return br.ready();
		}

	}

}