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

public class Main{
	 static long dp[][][][]=new long [16][16][16][4];
	 static void ini() {
		 for(int i=0;i<16;i++) {
			 for(int j=0;j<16;j++) {
				 for(int k=0;k<16;k++) {
					 for(int l=0;l<4;l++) {
						 dp[i][j][k][l]=-1L;
					 }
				 }
			 }
		 }
	 }
	 static int chk(long i) {
		 if(i==0L)
			 return 1;
		 else
			 return 0;
	 }
	 static long f(long a,long b,long c,int taken) {
		int got=(int) (a+b+c);
		int have=chk(a)+chk(b)+chk(c);
		if(have==2) {
			if(got==1)
				return 1L;
			else
				return 0L;
		}
		if(dp[(int) a][(int) b][(int) c][taken]!=-1) {
			return dp[(int) a][(int) b][(int) c][taken];
		}
		long ans=0L;
		 if(taken == 0) {
			 if(a!=0)
			 ans+=(a*f(a-1,b,c,1))%mod; ans%=mod;
			 if(b!=0)
			 ans+=(b*f(a,b-1,c,2))%mod; ans%=mod;
			 if(c!=0)
			 ans+=(c*f(a,b,c-1,3))%mod; ans%=mod;
		 }
		 else {
			 ans+=((taken==1 || a==0)?0L:(a*f(a-1,b,c,1))%mod)%mod; ans%=mod;
			 ans+=((taken==2 || b==0)?0L:(b*f(a,b-1,c,2))%mod)%mod; ans%=mod;
			 ans+=((taken==3 || c==0)?0L:(c*f(a,b,c-1,3))%mod)%mod; ans%=mod;
		 }
		 dp[(int) a][(int) b][(int) c][taken]=ans;
		 return ans;
	 }
	public static void main(String[] args)
   {
       InputReader in=new InputReader(System.in);
       PrintWriter pw = new PrintWriter(System.out);
       int n=in.nextInt();
       int total=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 ans=0L;
       for(int i=0;i<(1<<n);i++) {
    	   int sum=0;
    	   int a[]=new int[4];
    	   for(int j=0;j<n;j++) {

    		   if(((i>>j)&1)==1) {
    			   sum+=t[j];
    			   a[g[j]]++;
    		   }
    	   }
    	   if(sum==total) {
    		   ini();
    		   ans=(ans+f(a[1],a[2],a[3],0))%mod;
    	   }
       }
       pw.println(ans);
       pw.flush();
       pw.close();

        }
         private static void debug(Object... o) {
     		System.out.println(Arrays.deepToString(o));
     	}
        static class InputReader
        {
        private final InputStream stream;
        private final byte[] buf = new byte[8192];
        private int curChar, snumChars;
        private SpaceCharFilter filter;

        public InputReader(InputStream stream)
        {
            this.stream = stream;
        }
        public 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++];
        }

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

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

        public int[] nextIntArray(int n)
        {
            int a[] = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = nextInt();
            }
            return a;
        }
        static class tri implements Comparable<tri> {
            int p, c, l;

            tri(int p, int c, int l) {
                this.p = p;
                this.c = c;
                this.l = l;
            }

            public int compareTo(tri o) {
                return Integer.compare(l, o.l);
            }
        }

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

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

        public 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
        {
            public boolean isSpaceChar(int ch);
        }
    }
        public static long mod = 1000000007;
        public static int d;
        public static int p;
        public static int q;

        public static int[] suffle(int[] a,Random gen)
        {
            int n = a.length;
            for(int i=0;i<n;i++)
            {
                int ind = gen.nextInt(n-i)+i;
                int temp = a[ind];
                a[ind] = a[i];
                a[i] = temp;
            }
            return a;
        }

        public static void swap(int a, int b){
            int temp = a;
            a = b;
            b = temp;
        }

       /* public static long primeFactorization(long n)
        {
             HashSet<Integer> a =new HashSet<Integer>();
        	long cnt=0;
            for(int i=2;i*i<=n;i++)
            {
                while(a%i==0)
                {
                    a.add(i);
                    a/=i;
                }
            }
            if(a!=1)
            	cnt++;
                //a.add(n);
            return cnt;
        }*/

        public static void sieve(boolean[] isPrime,int n)
        {
            for(int i=1;i<n;i++)
                isPrime[i] = true;

            isPrime[0] = false;
            isPrime[1] = false;

            for(int i=2;i*i<n;i++)
            {
                if(isPrime[i] == true)
                {
                    for(int j=(2*i);j<n;j+=i)
                        isPrime[j] = false;
                }
            }
        }

        public static int GCD(int a,int b)
        {
            if(b==0)
                return a;
            else
                return GCD(b,a%b);
        }

        public static long GCD(long a,long b)
        {
            if(b==0)
                return a;
            else
                return GCD(b,a%b);
        }

        public static void extendedEuclid(int A,int B)
        {
            if(B==0)
            {
                d = A;
                p = 1 ;
                q = 0;
            }
            else
            {
                extendedEuclid(B, A%B);
                int temp = p;
                p = q;
                q = temp - (A/B)*q;
            }
        }

        public static long LCM(long a,long b)
        {
            return (a*b)/GCD(a,b);
        }

        public static int LCM(int a,int b)
        {
            return (a*b)/GCD(a,b);
        }

        public static int binaryExponentiation(int x,int n)
        {
            int result=1;
            while(n>0)
            {
                if(n % 2 ==1)
                    result=result * x;
                x=x*x;
                n=n/2;
            }
            return result;
        }

        public static long binaryExponentiation(long x,long n)
        {
            long result=1;
            while(n>0)
            {
                if(n % 2 ==1)
                    result=result * x;
                x=x*x;
                n=n/2;
            }
            return result;
        }

        public static int modularExponentiation(int x,int n,int M)
        {
            int result=1;
            while(n>0)
            {
                if(n % 2 ==1)
                    result=(result * x)%M;
                x=(x%M*x)%M;
                n=n/2;
            }
            return result;
        }

        public static long modularExponentiation(long x,long n,long M)
        {
            long result=1;
            while(n>0)
            {
                if(n % 2 ==1)
                    result=(result%M * x%M)%M;
                x=(x%M * x%M)%M;
                n=n/2;
            }
            return result;
        }

        public static long modInverse(int A,int M)
        {
            return modularExponentiation(A,M-2,M);
        }

        public static long modInverse(long A,long M)
        {
            return modularExponentiation(A,M-2,M);
        }

        public static boolean isPrime(int n)
        {

            if (n <= 1)  return false;
            if (n <= 3)  return true;

            if (n%2 == 0 || n%3 == 0)
                return false;

            for (int i=5; i*i<=n; i=i+6)
            {
                if (n%i == 0 || n%(i+2) == 0)
                   return false;
            }

            return true;
        }

         public static long[] shuffle(long[] a, Random gen){
                for(int i = 0, n = a.length;i < n;i++){
                    int ind = gen.nextInt(n-i)+i;
                    long d = a[i];
                    a[i] = a[ind];
                    a[ind] = d;
                }
                return a;
            }
         static class pair implements Comparable<pair>{
        	 Long x;
             Long y;
             Integer z;
             pair(long l,long y2,int z){
                 this.x=l;
                 this.y=y2;
                 this.z=z;
             }
              public int compareTo(pair o) {
                     int result = x.compareTo(o.x);
                     if(result==0)
                         result = y.compareTo(o.y);

                 return result;
                 }
              public String toString(){
                 return (x+" "+y);
             }
       }

}


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

public class Songs {

	static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

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

        public Reader(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]; // line length
            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();
        }
    }

    static int findPos(int x, int ar[]){
        for(int i=0;i<ar.length;i++){
            if(ar[i]==x)
                return (i+1);
        }
        return -20;
    }

    public static void main(String args[])throws IOException{
        Reader sc=new Reader();
        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int i,j;
        int n=sc.nextInt();
        int tt=sc.nextInt();
        int t[]=new int[n];
        int g[]=new int[n];
        int last=0;
        int M=1000000007;
        long sum=0;
        for(i=0;i<n;i++){
            t[i]=sc.nextInt();
            g[i]=sc.nextInt()-1;
        }
        int d[][]=new int[1<<n][4];
        d[0][3]=1;
        for(i=0;i<(1<<n);i++){
            for(last=0;last<4;last++){
                for(j=0;j<n;j++){
                    if(g[j]!=last&&((i&(1<<j)))==0){
                        d[i^(1<<j)][g[j]]=(d[i^(1<<j)][g[j]]+d[i][last])%M;
                        // System.out.println((i|(1<<j))+" "+(g[j])+" "+d[i|(1<<j)][g[j]]);
                    }
                }
            }
            int dur=0;
            for(j=0;j<n;j++){
                if((i&(1<<j))>0){
                    dur+=t[j];
                }
            }
            if(dur==tt){
                // System.out.println(i);
                sum=(sum+d[i][0]+d[i][1]+d[i][2])%M;
            }
        }
        pw.println(sum);
        pw.close();
    }
}

1185_G1. Playlist for Polycarp (easy version)


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

public class G1_PlaylistForPolycarp {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader inp = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver solver = new Solver();
        solver.solve(inp, out);
        out.close();
    }

    private static class Solver {
        private void solve(InputReader inp, PrintWriter out) {
            int n = inp.nextInt(), t = inp.nextInt();
            int[][] tracks = new int[n][2];
            long MOD = 1000000007;
            for (int i = 0; i < n; i++) {
                tracks[i][0] = inp.nextInt();
                tracks[i][1] = inp.nextInt() - 1;
            }
            long[][] dp = new long[2 << n][4];
            dp[0][3] = 1;

            // amount of 1's in the mask
            int curr = 1;
            while (curr <= n) {
                int mask = 0;
                for (int i = 0; i < curr; i++) mask |= (1 << i);

                // while it is a possible mask
                while (mask < 2 << n) {
                    // for each track
                    for (int i = 0; i < n; i++) {
                        // if mask contains track i
                        if ((mask & (1 << i)) != 0) {
                            // for each genre
                            for (int j = 0; j < 4; j++) {
                                if (j == tracks[i][1]) continue;
                                dp[mask][tracks[i][1]] += dp[mask - (1 << i)][j];
                            }
                        }
                    }

                    // update mask
                    mask = nextNumberXBits(mask);
                }
                curr++;
            }

            long res = 0;
            for (int i = 0; i < (2 << n); i++) {
                int time = 0;
                for (int j = 0; j < n; j++) {
                    if ((i & (1 << j)) != 0) time += tracks[j][0];
                }
                if (time == t) {
                    for (int j = 0; j < 4; j++) {
                        res += dp[i][j];
                    }
                    res %= MOD;
                }
            }
            out.print(res);
        }

        private static int nextNumberXBits(int mask) {
            int c = mask & -mask;
            int r = mask + c;
            return (((r ^ mask) >> 2) / c) | r;
        }
    }

    static class InputReader {
        BufferedReader reader;
        StringTokenizer tokenizer;

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

        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());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
    }
}


// Problem : G1. Playlist for Polycarp (easy version)
// Contest : Codeforces - Codeforces Round #568 (Div. 2)
// URL : https://codeforces.com/contest/1185/problem/G1
// Memory Limit : 256 MB
// Time Limit : 5000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)

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

public class a implements Runnable{

    public static void main(String[] args) {
        new Thread(null, new a(), "process", 1<<26).start();
    }
	public void run() {
		FastReader scan = new FastReader();
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		//PrintWriter out = new PrintWriter("file.out");
		Task solver = new Task();
		//int t = scan.nextInt();
		int t = 1;
		for(int i = 1; i <= t; i++) solver.solve(i, scan, out);
		out.close();
	}

	static class Task {
		static final int inf = Integer.MAX_VALUE;

		public void solve(int testNumber, FastReader sc, PrintWriter pw) {
			//CHECK FOR QUICKSORT TLE
			//***********************//
			//CHECK FOR INT OVERFLOW
			//***********************//
			int n = sc.nextInt();
			int m = sc.nextInt();
			tup[] arr = new tup[n];
			for(int i = 0; i < n; i++) {
				arr[i] = new tup(sc.nextInt(), sc.nextInt()-1);
			}
			List<Integer>[] arr2 = Stream.generate(ArrayList::new).limit(16).toArray(List[]::new);
			for(int i = 1; i < (1<<n); i++) {
				int t = i;
				int bits = 0;
				while(t > 0) {
					if((t & 1) == 1) bits ++;
					t>>=1;
				}
				arr2[bits].add(i);
			}
			int[][] dp = new int[1<<n][3];
			dp[0] = new int[]{1, 1, 1};
			long c = 0;
			for(int i = 1; i <= n; i++) {
				for(int x : arr2[i]) {
					int totallen = 0;
					ArrayList<Integer> active = new ArrayList<>();
					for(int j = 0; j < n; j++) {
						if((x & (1 << j)) > 0){
							active.add(j);
							totallen += arr[j].a;
						}
					}
					for(int y : active) {
						if(i == 1) dp[x][arr[y].b]++;
						else dp[x][arr[y].b] += dp[x - (1<<y)][(arr[y].b+1)%3] + dp[x - (1<<y)][(arr[y].b+2)%3];
						dp[x][arr[y].b] %= 1000000007;
					}
					if(totallen == m) {
						c += dp[x][0] + dp[x][1] + dp[x][2];
						c %= 1000000007;
					}
				}
			}
			pw.println(c);
		}
	}
	static long binpow(long a, long b, long m) {
		a %= m;
		long res = 1;
		while (b > 0) {
			if ((b & 1) == 1)
				res = res * a % m;
			a = a * a % m;
			b >>= 1;
		}
		return res;
	}
	static void sort(int[] x){
		shuffle(x);
		Arrays.sort(x);
	}
	static void sort(long[] x){
		shuffle(x);
		Arrays.sort(x);
	}
	static class tup implements Comparable<tup>{
		int a, b;
		tup(int a,int b){
			this.a=a;
			this.b=b;
		}
		@Override
		public int compareTo(tup o){
			return Integer.compare(o.b,b);
		}
	}
	static void shuffle(int[] a) {
		Random get = new Random();
		for (int i = 0; i < a.length; i++) {
			int r = get.nextInt(i + 1);
			int temp = a[i];
			a[i] = a[r];
			a[r] = temp;
		}
	}

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

	static class FastReader {
		BufferedReader br;
		StringTokenizer st;

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

		public FastReader(String s) throws FileNotFoundException {
			br = new BufferedReader(new FileReader(new File(s)));
		}

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

}


// 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];
            for(int i=0;i<A.length;i++){
                A[i][0]=Int();
                A[i][1]=Int()-1;
            }
            Arrays.sort(A,(a,b)->{
                return a[1]-b[1];
            });

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

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

        //init
        long f[]=new long[n+1];
        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<=n;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<=n;cnt++){
                    for(int j=0;j<dp1[0].length;j++){
                        newdp[cnt][j]+=dp1[cnt][j];
                        newdp[cnt][j]%=mod;
                    }
                }
                dp1=newdp;

            }
            else{
                break;
            }
        }

        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;
        dfs(n,n,n,0);dfs(n,n,n,1);dfs(n,n,n,2);

        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];
                            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(dp3[1][0][0][0]+"  "+dp2[0][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
*/


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.*;

public class CFContest {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e9 + 2;
        BitOperator bitOperator = new BitOperator();
        Modular modular = new Modular((int) 1e9 + 7);

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        int[][][] f;
        int n;
        int t;
        int[] songTimes;
        int[] songTypes;
        int mask;

        public void solve() {
            n = io.readInt();
            t = io.readInt();
            mask = 1 << n;
            f = new int[4][mask][t + 1];
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < mask; j++) {
                    for (int k = 0; k <= t; k++) {
                        f[i][j][k] = -1;
                    }
                }
            }

            songTimes = new int[n + 1];
            songTypes = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                songTimes[i] = io.readInt();
                songTypes[i] = io.readInt();
            }

            int ans = 0;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < mask; j++) {
                    ans = modular.plus(ans, f(i, j, t));
                }
            }

            io.cache.append(ans);
        }

        int f(int i, int j, int k) {
            if (j == 0) {
                return k == 0 && i == 0 ? 1 : 0;
            }
            if (k < 0) {
                return 0;
            }
            if (f[i][j][k] == -1) {
                f[i][j][k] = 0;
                for (int x = 1; x <= n; x++) {
                    if (songTypes[x] != i || bitOperator.bitAt(j, x - 1) == 0) {
                        continue;
                    }
                    for (int y = 0; y < 4; y++) {
                        if (y == i) {
                            continue;
                        }
                        f[i][j][k] = modular.plus(f[i][j][k], f(y, bitOperator.setBit(j, x - 1, false), k - songTimes[x]));
                    }
                }
            }
            return f[i][j][k];
        }
    }

    /**
     * 模运算
     */
    public static class Modular {
        int m;

        public Modular(int m) {
            this.m = m;
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        @Override
        public String toString() {
            return "mod " + m;
        }
    }

    public static class BitOperator {
        public int bitAt(int x, int i) {
            return (x >> i) & 1;
        }

        public int bitAt(long x, int i) {
            return (int) ((x >> i) & 1);
        }

        public int setBit(int x, int i, boolean v) {
            if (v) {
                x |= 1 << i;
            } else {
                x &= ~(1 << i);
            }
            return x;
        }

        public long setBit(long x, int i, boolean v) {
            if (v) {
                x |= 1L << i;
            } else {
                x &= ~(1L << i);
            }
            return x;
        }

        /**
         * Determine whether x is subset of y
         */
        public boolean subset(long x, long y) {
            return intersect(x, y) == x;
        }

        /**
         * Merge two set
         */
        public long merge(long x, long y) {
            return x | y;
        }

        public long intersect(long x, long y) {
            return x & y;
        }

        public long differ(long x, long y) {
            return x - intersect(x, y);
        }
    }

    public static class Randomized {
        static Random random = new Random();

        public static double nextDouble(double min, double max) {
            return random.nextDouble() * (max - min) + min;
        }

        public static void randomizedArray(int[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                int tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static void randomizedArray(long[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                long tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static void randomizedArray(double[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                double tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static void randomizedArray(float[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                float tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static <T> void randomizedArray(T[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                T tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static int nextInt(int l, int r) {
            return random.nextInt(r - l + 1) + l;
        }
    }

    public static class Splay implements Cloneable {
        public static final Splay NIL = new Splay();

        static {
            NIL.left = NIL;
            NIL.right = NIL;
            NIL.father = NIL;
            NIL.size = 0;
            NIL.key = Integer.MIN_VALUE;
            NIL.sum = 0;
        }

        Splay left = NIL;
        Splay right = NIL;
        Splay father = NIL;
        int size = 1;
        int key;
        long sum;

        public static void splay(Splay x) {
            if (x == NIL) {
                return;
            }
            Splay y, z;
            while ((y = x.father) != NIL) {
                if ((z = y.father) == NIL) {
                    y.pushDown();
                    x.pushDown();
                    if (x == y.left) {
                        zig(x);
                    } else {
                        zag(x);
                    }
                } else {
                    z.pushDown();
                    y.pushDown();
                    x.pushDown();
                    if (x == y.left) {
                        if (y == z.left) {
                            zig(y);
                            zig(x);
                        } else {
                            zig(x);
                            zag(x);
                        }
                    } else {
                        if (y == z.left) {
                            zag(x);
                            zig(x);
                        } else {
                            zag(y);
                            zag(x);
                        }
                    }
                }
            }

            x.pushDown();
            x.pushUp();
        }

        public static void zig(Splay x) {
            Splay y = x.father;
            Splay z = y.father;
            Splay b = x.right;

            y.setLeft(b);
            x.setRight(y);
            z.changeChild(y, x);

            y.pushUp();
        }

        public static void zag(Splay x) {
            Splay y = x.father;
            Splay z = y.father;
            Splay b = x.left;

            y.setRight(b);
            x.setLeft(y);
            z.changeChild(y, x);

            y.pushUp();
        }

        public void setLeft(Splay x) {
            left = x;
            x.father = this;
        }

        public void setRight(Splay x) {
            right = x;
            x.father = this;
        }

        public void changeChild(Splay y, Splay x) {
            if (left == y) {
                setLeft(x);
            } else {
                setRight(x);
            }
        }

        public void pushUp() {
            if (this == NIL) {
                return;
            }
            size = left.size + right.size + 1;
            sum = left.sum + right.sum + key;
        }

        public void pushDown() {
        }

        public static int toArray(Splay root, int[] data, int offset) {
            if (root == NIL) {
                return offset;
            }
            offset = toArray(root.left, data, offset);
            data[offset++] = root.key;
            offset = toArray(root.right, data, offset);
            return offset;
        }

        public static void toString(Splay root, StringBuilder builder) {
            if (root == NIL) {
                return;
            }
            root.pushDown();
            toString(root.left, builder);
            builder.append(root.key).append(',');
            toString(root.right, builder);
        }

        public Splay clone() {
            try {
                return (Splay) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException(e);
            }
        }

        public static Splay cloneTree(Splay splay) {
            if (splay == NIL) {
                return NIL;
            }
            splay = splay.clone();
            splay.left = cloneTree(splay.left);
            splay.right = cloneTree(splay.right);
            return splay;
        }

        public static Splay add(Splay root, Splay node) {
            if (root == NIL) {
                return node;
            }
            Splay p = root;
            while (root != NIL) {
                p = root;
                root.pushDown();
                if (root.key < node.key) {
                    root = root.right;
                } else {
                    root = root.left;
                }
            }

            if (p.key < node.key) {
                p.setRight(node);
            } else {
                p.setLeft(node);
            }
            p.pushUp();
            splay(node);
            return node;
        }

        /**
         * Make the node with the minimum key as the root of tree
         */
        public static Splay selectMinAsRoot(Splay root) {
            if (root == NIL) {
                return root;
            }
            root.pushDown();
            while (root.left != NIL) {
                root = root.left;
                root.pushDown();
            }
            splay(root);
            return root;
        }

        /**
         * Make the node with the maximum key as the root of tree
         */
        public static Splay selectMaxAsRoot(Splay root) {
            if (root == NIL) {
                return root;
            }
            root.pushDown();
            while (root.right != NIL) {
                root = root.right;
                root.pushDown();
            }
            splay(root);
            return root;
        }

        /**
         * delete root of tree, then merge remain nodes into a new tree, and return the new root
         */
        public static Splay deleteRoot(Splay root) {
            root.pushDown();
            Splay left = splitLeft(root);
            Splay right = splitRight(root);
            return merge(left, right);
        }

        /**
         * detach the left subtree from root and return the root of left subtree
         */
        public static Splay splitLeft(Splay root) {
            root.pushDown();
            Splay left = root.left;
            left.father = NIL;
            root.setLeft(NIL);
            root.pushUp();
            return left;
        }

        /**
         * detach the right subtree from root and return the root of right subtree
         */
        public static Splay splitRight(Splay root) {
            root.pushDown();
            Splay right = root.right;
            right.father = NIL;
            root.setRight(NIL);
            root.pushUp();
            return right;
        }

        public static Splay merge(Splay a, Splay b) {
            if (a == NIL) {
                return b;
            }
            if (b == NIL) {
                return a;
            }
            a = selectMaxAsRoot(a);
            a.setRight(b);
            a.pushUp();
            return a;
        }

        public static Splay selectKthAsRoot(Splay root, int k) {
            if (root == NIL) {
                return NIL;
            }
            Splay trace = root;
            Splay father = NIL;
            while (trace != NIL) {
                father = trace;
                trace.pushDown();
                if (trace.left.size >= k) {
                    trace = trace.left;
                } else {
                    k -= trace.left.size + 1;
                    if (k == 0) {
                        break;
                    } else {
                        trace = trace.right;
                    }
                }
            }
            splay(father);
            return father;
        }

        public static Splay selectKeyAsRoot(Splay root, int k) {
            if (root == NIL) {
                return NIL;
            }
            Splay trace = root;
            Splay father = NIL;
            Splay find = NIL;
            while (trace != NIL) {
                father = trace;
                trace.pushDown();
                if (trace.key > k) {
                    trace = trace.left;
                } else {
                    if (trace.key == k) {
                        find = trace;
                        trace = trace.left;
                    } else {
                        trace = trace.right;
                    }
                }
            }

            splay(father);
            if (find != NIL) {
                splay(find);
                return find;
            }
            return father;
        }

        public static Splay bruteForceMerge(Splay a, Splay b) {
            if (a == NIL) {
                return b;
            } else if (b == NIL) {
                return a;
            }
            if (a.size < b.size) {
                Splay tmp = a;
                a = b;
                b = tmp;
            }

            a = selectMaxAsRoot(a);
            int k = a.key;
            while (b != NIL) {
                b = selectMinAsRoot(b);
                if (b.key >= k) {
                    break;
                }
                Splay kickedOut = b;
                b = deleteRoot(b);
                a = add(a, kickedOut);
            }
            return merge(a, b);
        }

        public static Splay[] split(Splay root, int key) {
            if (root == NIL) {
                return new Splay[]{NIL, NIL};
            }
            Splay p = root;
            while (root != NIL) {
                p = root;
                root.pushDown();
                if (root.key > key) {
                    root = root.left;
                } else {
                    root = root.right;
                }
            }

            splay(p);
            if (p.key <= key) {
                return new Splay[]{p, splitRight(p)};
            } else {
                return new Splay[]{splitLeft(p), p};
            }
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder().append(key).append(":");
            toString(cloneTree(this), builder);
            return builder.toString();
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


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[4][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(3, 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] && 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));
    }
}


/*
Roses are red
Memes are neat
All my test cases time out
Lmao yeet
*/
import java.util.*;
import java.io.*;

   public class x1185G1b
   {
      static long MOD = 1000000007L;
      public static void main(String args[]) throws Exception
      {
         BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));
         StringTokenizer st = new StringTokenizer(infile.readLine());
         int N = Integer.parseInt(st.nextToken());
         int T = Integer.parseInt(st.nextToken());
         Song[] arr = new Song[N];
         for(int i=0; i < N; i++)
         {
            st = new StringTokenizer(infile.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken())-1;
            arr[i] = new Song(a, b);
         }
         //bitmask
         long[][] dp = new long[1 << N][3];
         Arrays.fill(dp[0], 1L);
         for(int mask=0; mask < dp.length; mask++)
         {
            for(int i=0; i < N; i++)
               if((mask & (1 << i)) == 0)
               {
                  Song c = arr[i];
                  //continue all dp if mask == 0
                  if(mask == 0 && c.t <= T)
                  {
                     dp[mask|(1 << i)][c.g]++;
                     dp[mask|(1 << i)][c.g] %= MOD;
                  }
                  //continue dp if not same genre
                  else
                  {
                     for(int gen=0; gen < 3; gen++)
                        if(gen != c.g)
                        {
                           dp[mask|(1 << i)][c.g] += dp[mask][gen];
                           dp[mask|(1 << i)][c.g] %= MOD;
                        }
                        //optimize?
                  }
               }
         }
         long res = 0L;
         for(int mask=1; mask < dp.length; mask++)
            for(int i=0; i < 3; i++)
            {
               int sum = 0;
               for(int b=0; b < N; b++)
                  if((mask & (1 << b)) > 0)
                     sum += arr[b].t;
               if(sum == T)
                  res = (res+dp[mask][i])%MOD;
            }
         System.out.println(res);
      }
   }
   class Song
   {
      public int t;
      public int g;

      public Song(int a, int b)
      {
         t = a;
         g = b;
      }
   }
   //cheerios are good for your heart, but are they good for your brain?


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.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author beginner1010
 */
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);
        TaskG1 solver = new TaskG1();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskG1 {
        final int mod = (int) 1e9 + 7;
        int[][][] dp;

        int rec(int mask, int time, int T, int genre, int[] ts, int[] gs) {
            if (time > T)
                return 0;
            if (time == T)
                return 1;
            if (mask == (1 << ts.length) - 1)
                return 0;
            int res = dp[genre][time][mask];
            if (res != -1)
                return res;
            res = 0;
            for (int i = 0; i < ts.length; i++) {
                if ((mask & (1 << i)) == 0 && (mask == 0 || gs[i] != genre)) {
                    res += rec(mask | (1 << i), time + ts[i], T, gs[i], ts, gs);
                    if (res >= mod)
                        res -= mod;
                }
            }
            return dp[genre][time][mask] = res;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int[] ts = new int[n];
            int[] gs = new int[n];
            int T = in.nextInt();
            for (int i = 0; i < n; i++) {
                ts[i] = in.nextInt();
                gs[i] = in.nextInt() - 1;
            }
            dp = new int[3][T][1 << n];
            for (int[][] aux : dp) {
                for (int[] aux2 : aux)
                    Arrays.fill(aux2, -1);
            }
            int ans = rec(0, 0, T, 0, ts, gs);
            out.println(ans);
        }

    }

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

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

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

        private 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 (isWhitespace(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 (!isWhitespace(c));
            return res * sgn;
        }

    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
import java.util.Map.Entry;

public class  cf2{
	static int x0;
	static int y0;
	static int x1;
	static int y1;
	static HashMap<Integer,HashSet<Integer>>allowed;
	static HashMap<Integer,HashMap<Integer,Integer>>cost;
	static int []dx= {-1,-1,-1,0,0,0,1,1,1};
	static int []dy= {-1,0,1,-1,0,1,-1,0,1};
	static int highbound=(int)1e9;
	static boolean valid(int i,int j) {
		if(i>=1 && i<=highbound && j>=1 && j<=highbound && allowed.containsKey(i) && allowed.get(i).contains(j))return true;
		return false;
	}
	static long ans;
	static class Triple implements Comparable<Triple>
	{
		int i,j,cost;
		Triple(int x, int y, int z){i = x; j = y; cost = z;}

		public int compareTo(Triple t) {
			return this.cost - t.cost;
		}
		public String toString() {
			return i+" "+j+" "+cost;
		}

	}
	public static int dijkstra()
	{
		PriorityQueue<Triple> q = new PriorityQueue<Triple>();
		q.add(new Triple(x0,y0,0));
		HashMap<Integer,Integer>z=new HashMap<Integer,Integer>();z.put(y0,0);
		cost.put(x0,z);
		while(!q.isEmpty())
		{
			Triple cur = q.remove();
			//if(cur.i==x1 && cur.j==y1)continue;
			if(cur.cost > cost.getOrDefault(cur.i,new HashMap<Integer,Integer>()).getOrDefault(cur.j,1000000000))
				continue;
			for(int k = 0; k < 9; k++)
			{
				int x = cur.i + dx[k];
				int y = cur.j + dy[k];
				int c=cost.getOrDefault(x,new HashMap<Integer,Integer>()).getOrDefault(y,1000000000);
				if(valid(x,y) && cur.cost +1 < c)
				{
					HashMap<Integer,Integer>zz=new HashMap<Integer,Integer>();zz.put(y,cur.cost+1);
					cost.put(x,zz);
					q.add(new Triple(x,y,cur.cost+1));
				}
			}
		}

		return cost.getOrDefault(x1,new HashMap<Integer,Integer>()).getOrDefault(y1,-1);
	}
	static int t;static int n;
	static int []ds;
	static int []gs;
	static int [][]memo;
	static int dp(int lastg,int msk,int sum) {
		if(sum==t)return 1;
		if(msk==(1<<n)-1) {
			return 0;
		}
		if(memo[lastg][msk]!=-1)return memo[lastg][msk];
		int tot=0;
		for(int i=0;i<n;i++) {
			if(((1<<i)&msk)==0 && gs[i]!=lastg) {
				tot=(tot+dp(gs[i],msk|(1<<i),sum+ds[i]))%(1000000007);
			}
		}
		return memo[lastg][msk]=tot;
	}
    public static void main(String[] args) throws IOException{
        MScanner sc = new MScanner(System.in);
        PrintWriter pw=new PrintWriter(System.out);
        n=sc.nextInt();
        t=sc.nextInt();
        ds=new int[n];gs=new int[n];
        for(int i=0;i<n;i++) {
        	ds[i]=sc.nextInt();gs[i]=sc.nextInt();
        }
        memo=new int[4][1<<n];
        for(int []i:memo)Arrays.fill(i,-1);
        pw.println(dp(0, 0,0));
        pw.flush();
    }
    static long gcd(long a, long b) {

		if (b == 0)
			return a;
		return gcd(b, a % b);
	}
    static int[]primes;
    static int sizeofp=0;
	static int[] isComposite;

	static void sieve(int N)	// O(N log log N)
	{
		isComposite = new int[N+1];
		isComposite[0] = isComposite[1] = 1;
		primes = new int[N];

		for (int i = 2; i <= N; ++i)
			if (isComposite[i] == 0)
			{
				primes[sizeofp++]=i;;
				if(1l * i * i <= N)
					for (int j = i * i; j <= N; j += i)
						isComposite[j] = 1;
			}
	}
    static class pair implements Comparable<pair>{
    	int num;int idx;
    	pair(int x,int y){
    		num=x;idx=y;
    	}
		@Override
		public int compareTo(pair o) {
			if(num!=o.num) {
				return num-o.num;
			}
			return idx-o.idx;
		}
		 @Override
	       public int hashCode()
	       {
	           return Objects.hash(num,idx) ;
	       }
		public boolean equals(pair o) {
			if(this.compareTo(o)==0)return true;
			return false;
		}
		public String toString() {
			return "("+0+" "+0+")";
		}
    }
	static class MScanner
	{
	    StringTokenizer st;
	    BufferedReader br;

	    public MScanner(InputStream s){    br = new BufferedReader(new InputStreamReader(s));}

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

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

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

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

	    public double nextDouble() throws IOException
	    {
	        String x = next();
	        StringBuilder sb = new StringBuilder("0");
	        double res = 0, f = 1;
	        boolean dec = false, neg = false;
	        int start = 0;
	        if(x.charAt(0) == '-')
	        {
	            neg = true;
	            start++;
	        }
	        for(int i = start; i < x.length(); i++)
	            if(x.charAt(i) == '.')
	            {
	                res = Long.parseLong(sb.toString());
	                sb = new StringBuilder("0");
	                dec = true;
	            }
	            else
	            {
	                sb.append(x.charAt(i));
	                if(dec)
	                    f *= 10;
	            }
	        res += Long.parseLong(sb.toString()) / f;
	        return res * (neg?-1:1);
	    }

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

	}
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
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);
        G1PleilistDlyaPolikarpaUproshennayaVersiya solver = new G1PleilistDlyaPolikarpaUproshennayaVersiya();
        solver.solve(1, in, out);
        out.close();
    }

    static class G1PleilistDlyaPolikarpaUproshennayaVersiya {

        static final int MOD = (int) 1e9 + 7;
        int n;
        int t;
        int[][] a = new int[15][2];
        long[][] mem = new long[1 << 15][4];

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            for (int i = 0; i < (1 << 15); i++) {
                for (int h = 0; h < 4; h++) {
                    mem[i][h] = -1;
                }
            }
            n = in.nextInt();
            t = in.nextInt();
            for (int i = 0; i < n; i++) {
                a[i][0] = in.nextInt();
                a[i][1] = in.nextInt();
            }
            out.println(doit(0, 0, 0));
        }

        private long doit(int mask, int genre, int sum) {
            if (mem[mask][genre] != -1) {
                return mem[mask][genre];
            }
            if (sum > t) {
                mem[mask][genre] = 0;
                return mem[mask][genre];
            }
            if (sum == t) {
                mem[mask][genre] = 1;
                return mem[mask][genre];
            }
            long ct = 0;
            for (int i = 0; i < n; i++) {
                if ((mask & (1 << i)) > 0 || genre == a[i][1]) {
                    continue;
                }
                ct = (ct + doit(mask | (1 << i), a[i][1], sum + a[i][0])) % MOD;
            }

            mem[mask][genre] = ct;
            return mem[mask][genre];
        }
    }

    static class InputReader {

        public BufferedReader reader;
        public 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());
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
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 static final int GENRES_COUNT = 3;
        private int songsCount;
        private int totalDuration;
        private Song[] songs;
        private int[][][] mem;
        static final int mod = 1000000007;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            songsCount = in.nextInt();
            totalDuration = in.nextInt();

            songs = new Song[songsCount];

            for (int i = 0; i < songsCount; i++) {
                songs[i] = new Song(in.nextInt(), in.nextInt() - 1);
            }

            long ret = 0;
            int chosenSongs = 0;

            mem = new int[GENRES_COUNT + 1][][];
            for (int i = 0; i < GENRES_COUNT; i++) {
                mem[i] = new int[totalDuration + 1][];

                for (int j = 0; j <= totalDuration; j++) {
                    mem[i][j] = new int[1 << songsCount];

                    for (int k = 0; k < 1 << songsCount; k++) {
                        mem[i][j][k] = -1;
                    }
                }
            }

            for (int i = 0; i < songsCount; i++) {
                chosenSongs = 1 << i;
                ret += search(totalDuration - songs[i].duration, songs[i].genre, chosenSongs);
            }

            out.println(ret % mod);
        }

        private long search(int timeLeft, int lastGenre, int chosen) {
            if (timeLeft < 0) {
                return 0;
            }

            if (timeLeft == 0) {
                return 1;
            }

            if (mem[lastGenre][timeLeft][chosen] != -1) {
                return mem[lastGenre][timeLeft][chosen];
            }

            long ret = 0;

            for (int i = 0; i < songsCount; i++) {
                if (((1 << i) & chosen) == 0 && songs[i].genre != lastGenre) {
                    ret += search(timeLeft - songs[i].duration, songs[i].genre, chosen | 1 << i);
                    if (ret > mod) {
                        ret = ret % mod;
                    }
                }
            }
            mem[lastGenre][timeLeft][chosen] = (int) (ret % mod);

            return mem[lastGenre][timeLeft][chosen];
        }

        class Song {
            public int duration;
            public int genre;

            public Song(int duration, int genre) {
                this.duration = duration;
                this.genre = genre;
            }

        }

    }

    static class InputReader {
        public BufferedReader reader;
        public 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());
        }

    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.concurrent.ThreadLocalRandom;

public class Main2 {

    static int mod = 1000000007;
    static FastScanner scanner;

    public static void main(String[] args) {
        scanner = new FastScanner();
        int n = scanner.nextInt();
        int T = scanner.nextInt();

        int[][] songs = new int[n][2];
        for (int i = 0; i < n; i++) {
            songs[i][0] = scanner.nextInt();
            songs[i][1] = scanner.nextInt() - 1;
        }

        int[] mapping = new int[65536];
        int mask = 1;
        for (int k = 0; k < n; k++) {
            for (int i = 1; i < mapping.length; i++) {
                if ((i & mask) != 0) mapping[i] += songs[k][0];
            }
            mask <<= 1;
        }

        int[][][] dp = new int[17][65536][3];
        mask = 1;

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

        for (int i = 1; i < n; i++) {
            mask = 1;
            for (int k = 0; k < n; k++) {
                int cg = songs[k][1];

                int g1,g2;
                if (cg == 0) {g1 = 1; g2 = 2;}
                else if (cg == 1) {g1 = 0; g2 = 2;}
                else {g1 = 0; g2 = 1;}

                for (int j = 1; j < 65536; j++) {
                    if ((j & mask) != 0) continue;
                    dp[i + 1][j | mask][cg] = (dp[i + 1][j | mask][cg] + (dp[i][j][g1] + dp[i][j][g2]) % mod) % mod;
                }
                mask <<= 1;
            }
        }
        int res = 0;
        for (int k = 0; k < 17; k++)
        for (int i = 1; i < 65536; i++) {
            if (mapping[i] == T) res = (res + dp[k][i][0] + dp[k][i][1] + dp[k][i][2]) % mod;
        }
        System.out.println(res);
    }

    static long test(long[] b, long c, int maxSkipped, int startWith) {
        int skipped = 0;
        long lastSkipped = b[0];
        for (int i = startWith; i < b.length; i++) {
            long expected = b[0] + c * (i - skipped);
            if (b[i] != expected) {
                skipped++;
                lastSkipped = b[i];
                if (skipped > maxSkipped) {
                    return Long.MAX_VALUE;
                }
            }
        }
        return lastSkipped;
    }

    static boolean test2(long[] b, long c) {
        for (int i = 1; i < b.length; i++) {
            long expected = b[1] + c * (i - 1);
            if (b[i] != expected) {
                return false;
            }
        }
        return true;
    }

//    5 5
//    1 1 5 2 3

    static class WithIdx implements Comparable<WithIdx> {
        int val;
        int idx;

        public WithIdx(int val, int idx) {
            this.val = val;
            this.idx = idx;
        }

        @Override
        public int compareTo(WithIdx o) {
            if (val == o.val) {
                return Integer.compare(idx, o.idx);
            }
            return -Integer.compare(val, o.val);
        }
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

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

        String nextToken() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        String nextLine() {
            try {
                return br.readLine();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException();
            }
        }

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

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

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

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

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

        String[] nextStringArray(int n) {
            String[] res = new String[n];
            for (int i = 0; i < n; i++) res[i] = nextToken();
            return res;
        }
    }

    static class PrefixSums {
        long[] sums;

        public PrefixSums(long[] sums) {
            this.sums = sums;
        }

        public long sum(int fromInclusive, int toExclusive) {
            if (fromInclusive > toExclusive) throw new IllegalArgumentException("Wrong value");
            return sums[toExclusive] - sums[fromInclusive];
        }

        public static PrefixSums of(int[] ar) {
            long[] sums = new long[ar.length + 1];
            for (int i = 1; i <= ar.length; i++) {
                sums[i] = sums[i - 1] + ar[i - 1];
            }
            return new PrefixSums(sums);
        }

        public static PrefixSums of(long[] ar) {
            long[] sums = new long[ar.length + 1];
            for (int i = 1; i <= ar.length; i++) {
                sums[i] = sums[i - 1] + ar[i - 1];
            }
            return new PrefixSums(sums);
        }
    }

    static class ADUtils {
        static void sort(int[] ar) {
            Random rnd = ThreadLocalRandom.current();
            for (int i = ar.length - 1; i > 0; i--)
            {
                int index = rnd.nextInt(i + 1);
                // Simple swap
                int a = ar[index];
                ar[index] = ar[i];
                ar[i] = a;
            }
            Arrays.sort(ar);
        }

        static void reverse(int[] arr) {
            int last = arr.length / 2;
            for (int i = 0; i < last; i++) {
                int tmp = arr[i];
                arr[i] = arr[arr.length - 1 - i];
                arr[arr.length - 1 - i] = tmp;
            }
        }

        static void sort(long[] ar) {
            Random rnd = ThreadLocalRandom.current();
            for (int i = ar.length - 1; i > 0; i--)
            {
                int index = rnd.nextInt(i + 1);
                // Simple swap
                long a = ar[index];
                ar[index] = ar[i];
                ar[i] = a;
            }
            Arrays.sort(ar);
        }
    }

    static class MathUtils {
        static long[] FIRST_PRIMES = {
                2,     3,      5,      7,     11,     13,     17,     19,     23,     29,
                31,     37,     41,     43,     47,     53,     59,     61,     67,     71,
                73,     79,     83,     89  ,   97 ,    101,    103,    107,    109,    113,
                127,    131,    137,    139,    149,    151,    157,    163,    167,    173,
                179,    181,    191,    193,    197,    199,    211,    223,    227,    229,
                233,    239,    241,    251,    257,    263,    269,    271,    277,    281,
                283,    293,    307,    311,    313,    317,    331,    337,    347,    349,
                353,    359,    367,    373,    379,    383,    389,    397,    401,    409,
                419,    421,    431,    433,    439,    443,    449,    457,    461,    463,
                467,    479,    487,    491,    499,    503,    509,    521,    523,    541,
                547,    557,    563,    569,    571,    577,    587,    593,    599,    601,
                607,    613,    617,    619,    631,    641,    643,    647,    653,    659,
                661,    673,    677,    683,    691,    701,    709,    719,    727,    733,
                739,    743,    751,    757,    761,    769,    773,    787,    797,    809,
                811,    821,    823,    827,    829,    839,    853,    857,    859,    863,
                877,    881,    883,    887,    907,    911,    919,    929,    937,    941,
                947,    953,    967,    971,    977,    983,    991,    997,   1009,   1013,
                1019,   1021,   1031,   1033,   1039,   1049,   1051};

        static long[] primes(int to) {
            long[] all = new long[to + 1];
            long[] primes = new long[to + 1];
            all[1] = 1;
            int primesLength = 0;
            for (int i = 2; i <= to; i ++) {
                if (all[i] == 0) {
                    primes[primesLength++] = i;
                    all[i] = i;
                }
                for (int j = 0; j < primesLength && i * primes[j] <= to && all[i] >= primes[j]; j++) {
                    all[(int) (i * primes[j])] = primes[j];
                }
            }
            return Arrays.copyOf(primes, primesLength);
        }

        static long modpow(long b, long e, long m) {
            long result = 1;

            while (e > 0) {
                if ((e & 1) == 1) {
                    /* multiply in this bit's contribution while using modulus to keep
                     * result small */
                    result = (result * b) % m;
                }
                b = (b * b) % m;
                e >>= 1;
            }

            return result;
        }

        static long submod(long x, long y, long m) {
            return (x - y + m) % m;
        }
    }
}


import java.io.*;
import java.text.*;
import java.util.*;
import java.math.*;
public class G1 {
	public static void main(String[] args) throws Exception {
		new G1().run();
    }
    int MOD = 1_000_000_007;
	public void run() throws Exception {
		FastScanner f = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        int n = f.nextInt(), t = f.nextInt();
        int[][] dp = new int[1 << n][3];
        int[] tarr = new int[n];
        int[] garr = new int[n];
        for(int i = 0; i < n; i++) {
            tarr[i] = f.nextInt();
            garr[i] = f.nextInt()-1;
            if(tarr[i] <= t) dp[1 << i][garr[i]] = 1;
        }
        int[] time = new int[1 << n];
        for(int i = 0; i < dp.length; i++) {
            for(int bi = 0; bi < n; bi++)
                if((i & 1 << bi) != 0) time[i] += tarr[bi];
        }
        for(int i = 0; i < dp.length; i++) {
            int j = time[i];
                for(int k = 0; k < 3; k++) {
                    if(dp[i][k] == 0) continue;
                    for(int bi = 0; bi < n; bi++)
                        if(tarr[bi] + j <= t && (i & 1 << bi) == 0 && garr[bi] != k) {
                                    dp[i | 1 << bi][garr[bi]] =
                                        (dp[i | 1 << bi][garr[bi]] + dp[i][k]) % MOD;
                        }
                }
        }
        long ans = 0;
        for(int i = 0; i < dp.length; i++)
            for(int j = 0; j < 3; j++)
            if(time[i] == t) ans = (ans + dp[i][j]) % MOD;
        out.println(ans);
        out.flush();
	}
    static class FastScanner {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public FastScanner() {
            reader = new BufferedReader(new InputStreamReader(System.in), 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());
        }
        public long nextLong() {
        	return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
        public String nextLine() {
        	try {
        		return reader.readLine();
        	} catch(IOException e) {
        		throw new RuntimeException(e);
        	}
        }
    }
}


import java.util.*;
import java.io.*;
import java.text.*;
public class Main{
    //SOLUTION BEGIN
    //Into the Hardware Mode
    void pre() throws Exception{}
    int n, t;
    void solve(int TC) throws Exception{
        n = ni();t = ni();
        int[][] song = new int[n][];
        for(int i = 0; i< n; i++)song[i] = new int[]{ni(), ni()-1};
        long[][] dp = new long[1<<n][3];
        for(int i = 0; i< dp.length; i++)
            for(int j = 0; j< dp[i].length; j++)
                dp[i][j] = -1;
        pn(start(dp, song, 0, -1));
    }
    long start(long[][] dp, int[][] song, int mask, int prev){
        long ti = 0;
        for(int i = 0; i< n; i++){
            if(((mask>>i)&1)==1)ti+=song[i][0];
        }
        if(ti==t)return 1;
        if(prev != -1 && dp[mask][prev] != -1)return dp[mask][prev];
        long ans = 0;
        for(int i = 0; i< n; i++){
            if(((mask>>i)&1)==0 && song[i][1] != prev && ti+song[i][0] <= t)
                ans = (ans+start(dp, song, mask|(1<<i), song[i][1]))%mod;
        }
        if(prev!= -1)dp[mask][prev] = ans;
        return ans;
    }
    //SOLUTION END
    void hold(boolean b)throws Exception{if(!b)throw new Exception("Hold right there, Sparky!");}
    long mod = (long)1e9+7, IINF = (long)1e18;
    final int INF = (int)1e9, MX = (int)2e5+5;
    DecimalFormat df = new DecimalFormat("0.00000000000");
    double PI = 3.141592653589793238462643383279502884197169399, eps = 1e-8;
    static boolean multipleTC = false, memory = false;
    FastReader in;PrintWriter out;
    void run() throws Exception{
        in = new FastReader();
        out = new PrintWriter(System.out);
        //Solution Credits: Taranpreet Singh
        int T = (multipleTC)?ni():1;
        pre();for(int t = 1; t<= T; t++)solve(t);
        out.flush();
        out.close();
    }
    public static void main(String[] args) throws Exception{
        if(memory)new Thread(null, new Runnable() {public void run(){try{new Main().run();}catch(Exception e){e.printStackTrace();}}}, "1", 1 << 28).start();
        else new Main().run();
    }
    long gcd(long a, long b){return (b==0)?a:gcd(b,a%b);}
    int gcd(int a, int b){return (b==0)?a:gcd(b,a%b);}
    int bit(long n){return (n==0)?0:(1+bit(n&(n-1)));}
    void p(Object o){out.print(o);}
    void pn(Object o){out.println(o);}
    void pni(Object o){out.println(o);out.flush();}
    String n()throws Exception{return in.next();}
    String nln()throws Exception{return in.nextLine();}
    int ni()throws Exception{return Integer.parseInt(in.next());}
    long nl()throws Exception{return Long.parseLong(in.next());}
    double nd()throws Exception{return Double.parseDouble(in.next());}

    class FastReader{
        BufferedReader br;
        StringTokenizer st;
        public FastReader(){
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public FastReader(String s) throws Exception{
            br = new BufferedReader(new FileReader(s));
        }

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

        String nextLine() throws Exception{
            String str = "";
            try{
                str = br.readLine();
            }catch (IOException e){
                throw new Exception(e.toString());
            }
            return str;
        }
    }
}


import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class G1 {
    static final int mod = (int) (1e9 + 7);
    static final int UNCALC = -1;
    static int[][][] memo;
    static int n, t[], genre[];

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        n = sc.nextInt();
        t = new int[n];
        int T = sc.nextInt();
        genre = new int[n];
        for (int i = 0; i < n; i++) {
            t[i] = sc.nextInt();
            genre[i] = sc.nextInt();
        }
        memo = new int[4][1 << n][T+1];
        for (int[][] a : memo)
            for (int[] b : a)
                Arrays.fill(b, UNCALC);
        out.println(dp(0, 0, T));
        out.flush();
        out.close();
    }

    static int dp(int last, int mask, int rem) {
        if (rem==0) return 1;
        if (memo[last][mask][rem] != UNCALC) return memo[last][mask][rem];
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if (genre[i] == last || t[i] > rem || (mask & 1 << i) != 0) continue;
            cnt = (cnt + dp(genre[i], mask | 1 << i, rem - t[i]))%mod;
        }
        return memo[last][mask][rem] = cnt;
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream system) {
            br = new BufferedReader(new InputStreamReader(system));
        }

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

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

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

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

        public char nextChar() throws IOException {
            return next().charAt(0);
        }

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

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

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

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

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

        public double[] nextDoubleArray(int n) throws IOException {
            double[] ans = new double[n];
            for (int i = 0; i < n; i++)
                ans[i] = nextDouble();
            return ans;
        }

        public short nextShort() throws IOException {
            return Short.parseShort(next());
        }

    }

}


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);
 		for(int j=0;j<1<<n;j++){
 			letsgodp(j, 1);
 			letsgodp(j, 2);
 			letsgodp(j, 3);
 		}
 		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){
 				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