import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;

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

    static class TaskG2 {
        static final int MOD = 1000000000 + 7;
        static final int MAXN = 51;

        int getWays(int i, int j, int k, int l, int[][][][] ways, boolean[][][][] cached) {
            if (i + j + k == 0) return l == -1 ? 1 : 0;
            if (l < 0) return 0;
            if (cached[i][j][k][l]) return ways[i][j][k][l];
            int s = i + j + k;
            long value = 0;
            if (l == 0 && i != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i - 1, j, k, x, ways, cached);
                    }
            }
            if (l == 1 && j != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i, j - 1, k, x, ways, cached);
                    }
            }
            if (l == 2 && k != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i, j, k - 1, x, ways, cached);
                    }
            }
            ways[i][j][k][l] = (int) (value % MOD);
            cached[i][j][k][l] = true;
            return ways[i][j][k][l];
        }

        int totalWays(int i, int j, int k, int[][][][] ways, boolean[][][][] cached, int[] factorial) {
            long ret = 0;
            for (int l = 0; l < 3; l++) ret += getWays(i, j, k, l, ways, cached);
            ret *= factorial[i];
            ret %= MOD;

            ret *= factorial[j];
            ret %= MOD;

            ret *= factorial[k];
            ret %= MOD;

            return (int) ret;
        }

        int add(int type, int value, int[] sizes, int sum, int[][][][] dp) {
            sizes[type]++;
            if (type == 0) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 1; i <= sizes[0]; i++)
                        for (int j = 0; j <= sizes[1]; j++)
                            for (int k = 0; k <= sizes[2]; k++) {
                                dp[i][j][k][s] += dp[i - 1][j][k][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            if (type == 1) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 0; i <= sizes[0]; i++)
                        for (int j = 1; j <= sizes[1]; j++)
                            for (int k = 0; k <= sizes[2]; k++) {
//                            System.out.println(i + " " + j + " " + k + " " + s + " " + dp.length + " " + dp[0].length + " " + dp[0][0].length + " " + dp[0][0][0].length);
                                dp[i][j][k][s] += dp[i][j - 1][k][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            if (type == 2) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 0; i <= sizes[0]; i++)
                        for (int j = 0; j <= sizes[1]; j++)
                            for (int k = 1; k <= sizes[2]; k++) {
//                            System.out.println(i + " " + j + " " + k + " " + s + " " + dp.length + " " + dp[0].length + " " + dp[0][0].length + " " + dp[0][0][0].length);
                                dp[i][j][k][s] += dp[i][j][k - 1][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            return sum + value;
        }

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int[][][][] ways = new int[MAXN][MAXN][MAXN][3];
            boolean[][][][] cached = new boolean[MAXN][MAXN][MAXN][3];
//        Arrays.fill(ways, -1);

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

            ArrayList<Integer>[] ar = new ArrayList[3];
            for (int i = 0; i < 3; i++) ar[i] = new ArrayList<Integer>();
            int total_sum = 0;
            for (int i = 0; i < n; i++) {
                int t = in.nextInt(), g = in.nextInt();
                ar[g - 1].add(t);
                total_sum += t;
            }

            if (T > total_sum) {
                out.println(0);
                return;
            }
            int min_index = 0, mn = 0;

            for (int i = 0; i < 3; i++) {
                if (ar[i].size() > mn) {
                    mn = ar[i].size();
                    min_index = i;
                }
            }

            int[][][][] dp = new int[ar[(1 + min_index) % 3].size() + 1][ar[(2 + min_index) % 3].size() + 1][1][total_sum + 1];
            int[][][][] dp2 = new int[1][1][mn + 1][total_sum + 1];
            dp[0][0][0][0] = dp2[0][0][0][0] = 1;
            int[] sizes = {0, 0, 0};
            int sum = 0;
            int[] order = {(min_index + 1) % 3, (min_index + 2) % 3};
            int type = 0;
            for (int i : order) {
                for (int v : ar[i])
                    sum = add(type, v, sizes, sum, dp);
                type++;
            }
            sum = 0;
            sizes[0] = sizes[1] = sizes[2] = 0;
            for (int i : ar[min_index])
                sum = add(2, i, sizes, sum, dp2);
            int[] factorial = new int[MAXN];
            factorial[0] = 1;
            for (int i = 1; i < MAXN; i++)
                factorial[i] = (int) ((factorial[i - 1] * 1L * i) % MOD);

            long answer = 0;
            for (int i = 0; i < dp.length; i++)
                for (int j = 0; j < dp[0].length; j++)
                    for (int k = 0; k <= mn; k++)
                        for (int s = 0; s <= T; s++) {

                            long x = (dp[i][j][0][s] * 1L * totalWays(i, j, k, ways, cached, factorial)) % MOD;
                            x *= dp2[0][0][k][T - s];
                            x %= MOD;
                            answer += x;

                        }
            out.println(answer % MOD);
        }

    }

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

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

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

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

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

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

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

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void println(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
            writer.print('\n');
        }

        public void close() {
            writer.close();
        }

    }
}


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

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

1185_G2. Playlist for Polycarp (hard version)


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

public class B {

	static int n, t[], g[], MOD = (int) 1e9 + 7;
	static int[][][] memo1, memo2[], memo3[];

	static int dp1(int idx, int remCnt, int remSum) {
		if (idx == n)
			return remSum == 0 && remCnt==0 ? 1 : 0;
		if (memo1[idx][remCnt][remSum] != -1)
			return memo1[idx][remCnt][remSum];
		int ans = dp1(idx + 1, remCnt, remSum);
		if (g[idx] == 0 && t[idx] <= remSum && remCnt>0) {
			ans += dp1(idx + 1, remCnt - 1, remSum - t[idx]);
			if (ans >= MOD)
				ans -= MOD;
		}
		return memo1[idx][remCnt][remSum] = ans;
	}

	static int dp2(int idx, int remCnt1, int remCnt2, int remSum) {
		int all = remCnt1 + remCnt2;
		if (all == 0)
			return remSum == 0 ? 1 : 0;
		if (idx == n || remSum == 0)
			return 0;
		if (memo2[idx][remCnt1][remCnt2][remSum] != -1)
			return memo2[idx][remCnt1][remCnt2][remSum];
		int ans = dp2(idx + 1, remCnt1, remCnt2, remSum);
		if (t[idx] <= remSum) {
			if (g[idx] == 1 && remCnt1 > 0)
				ans += dp2(idx + 1, remCnt1 - 1, remCnt2, remSum - t[idx]);
			else if (g[idx] == 2 && remCnt2 > 0)
				ans += dp2(idx + 1, remCnt1, remCnt2 - 1, remSum - t[idx]);

		}

		return memo2[idx][remCnt1][remCnt2][remSum] = ans;
	}

	private static int dp3(int cnt0, int cnt1, int cnt2, int last) {
		if (cnt0 + cnt1 + cnt2 == 0)
			return 1;
		if (memo3[last][cnt0][cnt1][cnt2] != -1)
			return memo3[last][cnt0][cnt1][cnt2];
		long ans = 0;
		if (cnt0 > 0 && last != 0)
			ans += dp3(cnt0 - 1, cnt1, cnt2, 0);
		if (cnt1 > 0 && last != 1)
			ans += dp3(cnt0, cnt1 - 1, cnt2, 1);
		if (cnt2 > 0 && last != 2)
			ans += dp3(cnt0, cnt1, cnt2 - 1, 2);
		return memo3[last][cnt0][cnt1][cnt2] = (int) (ans % MOD);

	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n = sc.nextInt();
		int[] fac = new int[n + 1];
		t = new int[n];
		g = new int[n];
		int[] cnt = new int[3];
		fac[0] = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = (int) (i * 1L * fac[i - 1] % MOD);
		int T = sc.nextInt();
		for (int i = 0; i < n; i++) {
			t[i] = sc.nextInt();
			g[i] = sc.nextInt() - 1;
			cnt[g[i]]++;

		}
		memo1 = new int[n][cnt[0] + 1][T + 1];
		memo2 = new int[n][cnt[1] + 1][cnt[2] + 1][T + 1];
		memo3 = new int[4][cnt[0] + 1][cnt[1] + 1][cnt[2] + 1];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= cnt[0]; j++)
				Arrays.fill(memo1[i][j], -1);
			for (int j = 0; j <= cnt[1]; j++)
				for (int k = 0; k <= cnt[2]; k++)
					Arrays.fill(memo2[i][j][k], -1);

		}
		for (int i = 0; i < 4; i++)
			for (int j = 0; j <= cnt[0]; j++)
				for (int k = 0; k <= cnt[1]; k++)
					Arrays.fill(memo3[i][j][k], -1);
		int ans = 0;
		for (int cnt0 = 0; cnt0 <= cnt[0]; cnt0++)
			for (int sum0 = 0; sum0 <= T; sum0++)
				for (int cnt1 = 0; cnt1 <= cnt[1]; cnt1++)
					for (int cnt2 = 0; cnt2 <= cnt[2]; cnt2++) {
						long ways = dp1(0, cnt0, sum0) * 1L * dp2(0, cnt1, cnt2, T - sum0) % MOD;
						ways = ways * dp3(cnt0, cnt1, cnt2, 3) % MOD;
						ways *= fac[cnt0];
						ways %= MOD;
						ways *= fac[cnt1];
						ways %= MOD;
						ways *= fac[cnt2];
						ways %= MOD;
						ans += ways;
						if (ans >= MOD)
							ans -= MOD;
					}
		out.println(ans);
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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

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

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

	}

}


import java.io.*;
import java.text.*;
import java.util.*;
import java.math.*;
public class template {
	public static void main(String[] args) throws Exception {
		new template().run();
	}
	long MOD = 1_000_000_007;
	public void run() throws Exception {
		FastScanner f = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		int n = f.nextInt(), m = f.nextInt();
		int[] t = new int[n], g = new int[n], c = new int[3];
		for(int i = 0; i < n; i++) {
			t[i] = f.nextInt();
			c[g[i] = f.nextInt()-1]++;
		}
		long[][] dp1 = new long[c[0]+1][m+1];
		long[][][] dp2 = new long[c[1]+1][c[2]+1][m+1];
		dp1[0][0] = 1;
		dp2[0][0][0] = 1;
		for(int i = 0; i < n; i++) {
			if(g[i] == 0) {
				for(int j = dp1.length-2; j >= 0; j--)
					for(int k = m-t[i]; k >= 0; k--)
						dp1[j+1][k+t[i]] = (dp1[j+1][k+t[i]] + dp1[j][k]) % MOD;
			} else if(g[i] == 1) {
				for(int j = dp2.length-2; j >= 0; j--)
					for(int k = dp2[j].length-1; k >= 0; k--)
						for(int l = m-t[i]; l >= 0; l--)
							dp2[j+1][k][l+t[i]] = (dp2[j+1][k][l+t[i]] + dp2[j][k][l]) % MOD;
			} else {
				for(int j = dp2.length-1; j >= 0; j--)
					for(int k = dp2[j].length-2; k >= 0; k--)
						for(int l = m-t[i]; l >= 0; l--)
							dp2[j][k+1][l+t[i]] = (dp2[j][k+1][l+t[i]] + dp2[j][k][l]) % MOD;
			}
		}
		long[][][][] combo = new long[c[0]+1][c[1]+1][c[2]+1][3];
		if(c[0] != 0) combo[1][0][0][0] = 1;
		if(c[1] != 0) combo[0][1][0][1] = 1;
		if(c[2] != 0) combo[0][0][1][2] = 1;
		for(int i = 0; i <= c[0]; i++) {
			for(int j = 0; j <= c[1]; j++) {
				for(int k = 0; k <= c[2]; k++) {
					for(int a = 0; a < 3; a++) {
						if(a != 0 && i < c[0]) combo[i+1][j][k][0] = (combo[i+1][j][k][0] + combo[i][j][k][a] * (i+1) % MOD) % MOD;
						if(a != 1 && j < c[1]) combo[i][j+1][k][1] = (combo[i][j+1][k][1] + combo[i][j][k][a] * (j+1) % MOD) % MOD;
						if(a != 2 && k < c[2]) combo[i][j][k+1][2] = (combo[i][j][k+1][2] + combo[i][j][k][a] * (k+1) % MOD) % MOD;
					}
				}
			}
		}
		long ans = 0;
		for(int s = 0; s <= m; s++) {
			for(int x = 0; x <= c[0]; x++)
				for(int y = 0; y <= c[1]; y++)
					for(int z = 0;z <= c[2]; z++) {
						ans = (ans + dp1[x][s] * dp2[y][z][m-s] % MOD * ((combo[x][y][z][0] + combo[x][y][z][1] + combo[x][y][z][2]) % MOD) % MOD) % MOD;
					}
		}
		/*
		for(int i = 0; i < dp1.length; i++)
			out.println(Arrays.toString(dp1[i]));
		out.println("-----");
		for(int i = 0; i < dp2.length; i++) {
			for(int j = 0; j < dp2[i].length; j++)
					out.println(Arrays.toString(dp2[i][j]));
				out.println();
			}
		for(int i = 0; i <= c[0]; i++) for(int j = 0; j <= c[1]; j++) for(int k = 0; k <= c[2]; k++) out.printf("%d %d %d: %d%n", i, j, k, combo[i][j][k][0] + combo[i][j][k][1] + combo[i][j][k][2]); */
		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.io.*;
import java.util.*;

public class B {

	static int n,t[],g[],MOD=(int)1e9+7;
	static int [][][]memo1,memo2[],memo3[];
	static int dp1(int idx,int remCnt,int remSum) {
		if(remCnt==0)
			return remSum==0?1:0;
		if(remSum==0 || idx==n)
			return 0;
		if(memo1[idx][remCnt][remSum]!=-1)
			return memo1[idx][remCnt][remSum];
		int ans=dp1(idx+1,remCnt,remSum);
		if(g[idx]==0 && t[idx]<=remSum)
		{
			ans+=dp1(idx+1,remCnt-1,remSum-t[idx]);
			if(ans>=MOD)
				ans-=MOD;
		}
		return memo1[idx][remCnt][remSum]=ans;
	}
	static int dp2(int idx,int remCnt1,int remCnt2,int remSum) {
		int all=remCnt1+remCnt2;
		if(all==0)
			return remSum==0?1:0;
		if(idx==n || remSum==0)
			return 0;
		if(memo2[idx][remCnt1][remCnt2][remSum]!=-1)
			return memo2[idx][remCnt1][remCnt2][remSum];
		int ans=dp2(idx+1,remCnt1,remCnt2,remSum);
		if(t[idx]<=remSum) {
			if(g[idx]==1 && remCnt1>0)
				ans+=dp2(idx+1,remCnt1-1,remCnt2,remSum-t[idx]);
			else if(g[idx]==2 && remCnt2>0)
				ans+=dp2(idx+1,remCnt1,remCnt2-1,remSum-t[idx]);

		}

		return memo2[idx][remCnt1][remCnt2][remSum]=ans;
	}
	private static int dp3(int cnt0, int cnt1, int cnt2,int last) {
		if(cnt0+cnt1+cnt2==0)
			return 1;
		if(memo3[last][cnt0][cnt1][cnt2]!=-1)
			return memo3[last][cnt0][cnt1][cnt2];
		long ans=0;
		if(cnt0>0 && last!=0)
			ans+=dp3(cnt0-1,cnt1,cnt2,0);
		if(cnt1>0 && last!=1)
			ans+=dp3(cnt0,cnt1-1,cnt2,1);
		if(cnt2>0 && last!=2)
			ans+=dp3(cnt0,cnt1,cnt2-1,2);
		return  memo3[last][cnt0][cnt1][cnt2]=(int) (ans%MOD);

	}
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n=sc.nextInt();
		int []fac=new int [n+1];
		t=new int [n];
		g=new int [n];
		int []cnt=new int [3];
		fac[0]=1;
		for(int i=1;i<=n;i++)
			fac[i]=(int) (i*1L*fac[i-1]%MOD);
		int T=sc.nextInt();
		for(int i=0;i<n;i++) {
			t[i]=sc.nextInt();
			g[i]=sc.nextInt()-1;
			cnt[g[i]]++;

		}
		memo1=new int [n][cnt[0]+1][T+1];
		memo2=new int [n][cnt[1]+1][cnt[2]+1][T+1];
		memo3=new int [4][cnt[0]+1][cnt[1]+1][cnt[2]+1];
		for(int i=0;i<n;i++) {
			for(int j=0;j<=cnt[0];j++)
				Arrays.fill(memo1[i][j], -1);
			for(int j=0;j<=cnt[1];j++)
				for(int k=0;k<=cnt[2];k++)
					Arrays.fill(memo2[i][j][k], -1);

		}
		for(int i=0;i<4;i++)
			for(int j=0;j<=cnt[0];j++)
				for(int k=0;k<=cnt[1];k++)
					Arrays.fill(memo3[i][j][k], -1);
		int ans=0;
		for(int cnt0=0;cnt0<=cnt[0];cnt0++)
			for(int sum0=0;sum0<=T;sum0++)
				for(int cnt1=0;cnt1<=cnt[1];cnt1++)
					for(int cnt2=0;cnt2<=cnt[2];cnt2++) {
						long ways= dp1(0,cnt0,sum0)*1L*dp2(0,cnt1,cnt2,T-sum0)%MOD;
						ways=ways*dp3(cnt0,cnt1,cnt2,3)%MOD;
						ways*=fac[cnt0];
						ways%=MOD;
						ways*=fac[cnt1];
						ways%=MOD;
						ways*=fac[cnt2];
						ways%=MOD;
						ans+=ways;
						if(ans>=MOD)
							ans-=MOD;
					}
		out.println(ans);
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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

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

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

	}

}


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

public class B {

	static int n, t[], g[], MOD = (int) 1e9 + 7;
	static int[][][] memo1, memo2[], memo3[];

	static int dp1(int idx, int remCnt, int remSum) {
		if (idx == n)
			return remSum == 0 && remCnt == 0 ? 1 : 0;
		if (remCnt < 0 || remSum < 0)
			return 0;
		if (memo1[idx][remCnt][remSum] != -1)
			return memo1[idx][remCnt][remSum];
		int ans = dp1(idx + 1, remCnt, remSum);
		if (g[idx] == 0) {
			ans += dp1(idx + 1, remCnt - 1, remSum - t[idx]);
			if (ans >= MOD)
				ans -= MOD;
		}
		return memo1[idx][remCnt][remSum] = ans;
	}

	static int dp2(int idx, int remCnt1, int remCnt2, int remSum) {

		if (idx == n)
			return remSum == 0 && remCnt1 == 0 && remCnt2 == 0 ? 1 : 0;
		if (remSum < 0 || remCnt1 < 0 || remCnt2 < 0)
			return 0;
		if (memo2[idx][remCnt1][remCnt2][remSum] != -1)
			return memo2[idx][remCnt1][remCnt2][remSum];
		int ans = dp2(idx + 1, remCnt1, remCnt2, remSum);

		if (g[idx] == 1)
			ans += dp2(idx + 1, remCnt1 - 1, remCnt2, remSum - t[idx]);
		else if (g[idx] == 2)
			ans += dp2(idx + 1, remCnt1, remCnt2 - 1, remSum - t[idx]);

		return memo2[idx][remCnt1][remCnt2][remSum] = ans;
	}

	private static int dp3(int cnt0, int cnt1, int cnt2, int last) {
		if (cnt0 < 0 || cnt1 < 0 || cnt2 < 0)
			return 0;
		if (cnt0 + cnt1 + cnt2 == 0)
			return 1;
		if (memo3[last][cnt0][cnt1][cnt2] != -1)
			return memo3[last][cnt0][cnt1][cnt2];
		long ans = 0;
		if (last != 0)
			ans += dp3(cnt0 - 1, cnt1, cnt2, 0);
		if (last != 1)
			ans += dp3(cnt0, cnt1 - 1, cnt2, 1);
		if (last != 2)
			ans += dp3(cnt0, cnt1, cnt2 - 1, 2);
		return memo3[last][cnt0][cnt1][cnt2] = (int) (ans % MOD);

	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n = sc.nextInt();
		int[] fac = new int[n + 1];
		t = new int[n];
		g = new int[n];
		int[] cnt = new int[3];
		fac[0] = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = (int) (i * 1L * fac[i - 1] % MOD);
		int T = sc.nextInt();
		for (int i = 0; i < n; i++) {
			t[i] = sc.nextInt();
			g[i] = sc.nextInt() - 1;
			cnt[g[i]]++;

		}
		memo1 = new int[n][cnt[0] + 1][T + 1];
		memo2 = new int[n][cnt[1] + 1][cnt[2] + 1][T + 1];
		memo3 = new int[4][cnt[0] + 1][cnt[1] + 1][cnt[2] + 1];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= cnt[0]; j++)
				Arrays.fill(memo1[i][j], -1);
			for (int j = 0; j <= cnt[1]; j++)
				for (int k = 0; k <= cnt[2]; k++)
					Arrays.fill(memo2[i][j][k], -1);

		}
		for (int i = 0; i < 4; i++)
			for (int j = 0; j <= cnt[0]; j++)
				for (int k = 0; k <= cnt[1]; k++)
					Arrays.fill(memo3[i][j][k], -1);
		int ans = 0;
		for (int cnt0 = 0; cnt0 <= cnt[0]; cnt0++)
			for (int sum0 = 0; sum0 <= T; sum0++)
				for (int cnt1 = 0; cnt1 <= cnt[1]; cnt1++)
					for (int cnt2 = 0; cnt2 <= cnt[2]; cnt2++) {
						long ways = dp1(0, cnt0, sum0) * 1L * dp2(0, cnt1, cnt2, T - sum0) % MOD;
						ways = ways * dp3(cnt0, cnt1, cnt2, 3) % MOD;
						ways *= fac[cnt0];
						ways %= MOD;
						ways *= fac[cnt1];
						ways %= MOD;
						ways *= fac[cnt2];
						ways %= MOD;
						ans += ways;
						if (ans >= MOD)
							ans -= MOD;
					}
		out.println(ans);
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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

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

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

	}

}


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

public class B {

	static int n, t[], g[], MOD = (int) 1e9 + 7;
	static int[][][] memo1, memo2[], memo3[];

	static int dp1(int idx, int remCnt, int remSum) {
		if (idx == n)
			return remSum == 0 && remCnt == 0 ? 1 : 0;
		if (remCnt < 0 || remSum < 0)
			return 0;
		if (memo1[idx][remCnt][remSum] != -1)
			return memo1[idx][remCnt][remSum];
		int ans = dp1(idx + 1, remCnt, remSum);
		if (g[idx] == 0) {
			ans += dp1(idx + 1, remCnt - 1, remSum - t[idx]);
			if (ans >= MOD)
				ans -= MOD;
		}
		return memo1[idx][remCnt][remSum] = ans;
	}

	static int dp2(int idx, int remCnt1, int remCnt2, int remSum) {

		if (idx == n)
			return remSum == 0 && remCnt1 == 0 && remCnt2 == 0 ? 1 : 0;
		if (remSum < 0 || remCnt1 < 0 || remCnt2 < 0)
			return 0;
		if (memo2[idx][remCnt1][remCnt2][remSum] != -1)
			return memo2[idx][remCnt1][remCnt2][remSum];
		int ans = dp2(idx + 1, remCnt1, remCnt2, remSum);

		if (g[idx] == 1)
			ans += dp2(idx + 1, remCnt1 - 1, remCnt2, remSum - t[idx]);
		else if (g[idx] == 2)
			ans += dp2(idx + 1, remCnt1, remCnt2 - 1, remSum - t[idx]);
		if (ans >= MOD)
			ans -= MOD;
		return memo2[idx][remCnt1][remCnt2][remSum] = ans;
	}

	private static int dp3(int cnt0, int cnt1, int cnt2, int last) {
		if (cnt0 + cnt1 + cnt2 == 0)
			return 1;
		if (memo3[last][cnt0][cnt1][cnt2] != -1)
			return memo3[last][cnt0][cnt1][cnt2];
		long ans = 0;
		if (cnt0 > 0 && last != 0)
			ans += dp3(cnt0 - 1, cnt1, cnt2, 0);
		if (cnt1 > 0 && last != 1)
			ans += dp3(cnt0, cnt1 - 1, cnt2, 1);
		if (cnt2 > 0 && last != 2)
			ans += dp3(cnt0, cnt1, cnt2 - 1, 2);
		return memo3[last][cnt0][cnt1][cnt2] = (int) (ans % MOD);

	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n = sc.nextInt();
		int[] fac = new int[n + 1];
		t = new int[n];
		g = new int[n];
		int[] cnt = new int[3];
		fac[0] = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = (int) (i * 1L * fac[i - 1] % MOD);
		int T = sc.nextInt();
		for (int i = 0; i < n; i++) {
			t[i] = sc.nextInt();
			g[i] = sc.nextInt() - 1;
			cnt[g[i]]++;

		}
		memo1 = new int[n][cnt[0] + 1][T + 1];
		memo2 = new int[n][cnt[1] + 1][cnt[2] + 1][T + 1];
		memo3 = new int[4][cnt[0] + 1][cnt[1] + 1][cnt[2] + 1];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= cnt[0]; j++)
				Arrays.fill(memo1[i][j], -1);
			for (int j = 0; j <= cnt[1]; j++)
				for (int k = 0; k <= cnt[2]; k++)
					Arrays.fill(memo2[i][j][k], -1);

		}
		for (int i = 0; i < 4; i++)
			for (int j = 0; j <= cnt[0]; j++)
				for (int k = 0; k <= cnt[1]; k++)
					Arrays.fill(memo3[i][j][k], -1);
		int ans = 0;
		for (int cnt0 = 0; cnt0 <= cnt[0]; cnt0++)
			for (int sum0 = 0; sum0 <= T; sum0++)
				for (int cnt1 = 0; cnt1 <= cnt[1]; cnt1++)
					for (int cnt2 = 0; cnt2 <= cnt[2]; cnt2++) {
						long ways = dp1(0, cnt0, sum0) * 1L * dp2(0, cnt1, cnt2, T - sum0) % MOD;
						ways = ways * dp3(cnt0, cnt1, cnt2, 3) % MOD;
						ways *= fac[cnt0];
						ways %= MOD;
						ways *= fac[cnt1];
						ways %= MOD;
						ways *= fac[cnt2];
						ways %= MOD;
						ans += ways;
						if (ans >= MOD)
							ans -= MOD;
					}
		out.println(ans);
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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

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

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

	}

}


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

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

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

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

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

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

                if(A[i][1]==0)a++;
                else if(A[i][1]==1)b++;
                else c++;
            }
            Solution sol=new Solution(out);
            sol.solution(A,k,a,b,c);
        }
        out.close();

    }

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

}

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

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

        //System.out.println(x+" "+y+" "+z);

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

        dp1[0][0]=1;
        long newdp1[][]=new long[dp1.length][dp1[0].length];
        for(int i=0;i<A.length;i++){//a
            int p=A[i][0],type=A[i][1];
            if(type==0){

                for(int cnt=1;cnt<=x;cnt++){
                    for(int j=1;j<dp1[0].length;j++){
                        if(j>=p){
                            newdp1[cnt][j]+=dp1[cnt-1][j-p];
                            newdp1[cnt][j]%=mod;
                        }
                    }
                }

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

        dp2[0][0][0]=1;
        long newdp2[][][]=new long[dp2.length][dp2[0].length][dp2[0][0].length];

        for(int i=0;i<A.length;i++){//b c
            int p=A[i][0],type=A[i][1];
            if(type!=0){
                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){
                                        newdp2[a][b][j]+=dp2[a-1][b][j-p];
                                    }
                                }
                                else{
                                    if(b-1>=0) {
                                        newdp2[a][b][j]+=dp2[a][b-1][j-p];
                                    }
                                }
                            }
                            newdp2[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++){
                            dp2[a][b][j]+=newdp2[a][b][j];
                            dp2[a][b][j]%=mod;
                            newdp2[a][b][j]=0;
                        }
                    }
                }
            }//type!=0
        }

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

        for(int i=0;i<dp3.length-1;i++){
            for(int j=0;j<dp3[0].length-1;j++){
                for(int k=0;k<dp3[0][0].length-1;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;

                        }
                    }
                }
            }
        }
        out.println(res);

    }

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

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

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

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

}

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

                      free bug dog
*/

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


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

public class B {

	static int n, t[], g[], MOD = (int) 1e9 + 7;
	static int[][][] memo1, memo2[], memo3[];

	static int dp1(int idx, int remCnt, int remSum) {
		if (idx == n)
			return remSum == 0 && remCnt==0 ? 1 : 0;
		if(remCnt<0 || remSum<0)
			return 0;
		if (memo1[idx][remCnt][remSum] != -1)
			return memo1[idx][remCnt][remSum];
		int ans = dp1(idx + 1, remCnt, remSum);
		if (g[idx] == 0) {
			ans += dp1(idx + 1, remCnt - 1, remSum - t[idx]);
			if (ans >= MOD)
				ans -= MOD;
		}
		return memo1[idx][remCnt][remSum] = ans;
	}

	static int dp2(int idx, int remCnt1, int remCnt2, int remSum) {
		int all = remCnt1 + remCnt2;
		if (all == 0)
			return remSum == 0 ? 1 : 0;
		if (idx == n || remSum == 0)
			return 0;
		if (memo2[idx][remCnt1][remCnt2][remSum] != -1)
			return memo2[idx][remCnt1][remCnt2][remSum];
		int ans = dp2(idx + 1, remCnt1, remCnt2, remSum);
		if (t[idx] <= remSum) {
			if (g[idx] == 1 && remCnt1 > 0)
				ans += dp2(idx + 1, remCnt1 - 1, remCnt2, remSum - t[idx]);
			else if (g[idx] == 2 && remCnt2 > 0)
				ans += dp2(idx + 1, remCnt1, remCnt2 - 1, remSum - t[idx]);

		}

		return memo2[idx][remCnt1][remCnt2][remSum] = ans;
	}

	private static int dp3(int cnt0, int cnt1, int cnt2, int last) {
		if (cnt0 + cnt1 + cnt2 == 0)
			return 1;
		if (memo3[last][cnt0][cnt1][cnt2] != -1)
			return memo3[last][cnt0][cnt1][cnt2];
		long ans = 0;
		if (cnt0 > 0 && last != 0)
			ans += dp3(cnt0 - 1, cnt1, cnt2, 0);
		if (cnt1 > 0 && last != 1)
			ans += dp3(cnt0, cnt1 - 1, cnt2, 1);
		if (cnt2 > 0 && last != 2)
			ans += dp3(cnt0, cnt1, cnt2 - 1, 2);
		return memo3[last][cnt0][cnt1][cnt2] = (int) (ans % MOD);

	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n = sc.nextInt();
		int[] fac = new int[n + 1];
		t = new int[n];
		g = new int[n];
		int[] cnt = new int[3];
		fac[0] = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = (int) (i * 1L * fac[i - 1] % MOD);
		int T = sc.nextInt();
		for (int i = 0; i < n; i++) {
			t[i] = sc.nextInt();
			g[i] = sc.nextInt() - 1;
			cnt[g[i]]++;

		}
		memo1 = new int[n][cnt[0] + 1][T + 1];
		memo2 = new int[n][cnt[1] + 1][cnt[2] + 1][T + 1];
		memo3 = new int[4][cnt[0] + 1][cnt[1] + 1][cnt[2] + 1];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= cnt[0]; j++)
				Arrays.fill(memo1[i][j], -1);
			for (int j = 0; j <= cnt[1]; j++)
				for (int k = 0; k <= cnt[2]; k++)
					Arrays.fill(memo2[i][j][k], -1);

		}
		for (int i = 0; i < 4; i++)
			for (int j = 0; j <= cnt[0]; j++)
				for (int k = 0; k <= cnt[1]; k++)
					Arrays.fill(memo3[i][j][k], -1);
		int ans = 0;
		for (int cnt0 = 0; cnt0 <= cnt[0]; cnt0++)
			for (int sum0 = 0; sum0 <= T; sum0++)
				for (int cnt1 = 0; cnt1 <= cnt[1]; cnt1++)
					for (int cnt2 = 0; cnt2 <= cnt[2]; cnt2++) {
						long ways = dp1(0, cnt0, sum0) * 1L * dp2(0, cnt1, cnt2, T - sum0) % MOD;
						ways = ways * dp3(cnt0, cnt1, cnt2, 3) % MOD;
						ways *= fac[cnt0];
						ways %= MOD;
						ways *= fac[cnt1];
						ways %= MOD;
						ways *= fac[cnt2];
						ways %= MOD;
						ans += ways;
						if (ans >= MOD)
							ans -= MOD;
					}
		out.println(ans);
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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

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

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

	}

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;

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

    static class TaskG2 {
        static final int MOD = 1000000000 + 7;
        static final int MAXN = 51;

        int getWays(int i, int j, int k, int l, int[][][][] ways, boolean[][][][] cached) {
            if (i + j + k == 0) return l == -1 ? 1 : 0;
            if (l < 0) return 0;
            if (cached[i][j][k][l]) return ways[i][j][k][l];
            int s = i + j + k;
            long value = 0;
            if (l == 0 && i != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i - 1, j, k, x, ways, cached);
                    }
            }
            if (l == 1 && j != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i, j - 1, k, x, ways, cached);
                    }
            }
            if (l == 2 && k != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i, j, k - 1, x, ways, cached);
                    }
            }
            ways[i][j][k][l] = (int) (value % MOD);
            cached[i][j][k][l] = true;
            return ways[i][j][k][l];
        }

        int totalWays(int i, int j, int k, int[][][][] ways, boolean[][][][] cached, int[] factorial) {
            long ret = 0;
            for (int l = 0; l < 3; l++) ret += getWays(i, j, k, l, ways, cached);
            ret *= factorial[i];
            ret %= MOD;

            ret *= factorial[j];
            ret %= MOD;

            ret *= factorial[k];
            ret %= MOD;

            return (int) ret;
        }

        int add(int type, int value, int[] sizes, int sum, int[][][][] dp) {
            sizes[type]++;
            if (type == 0) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 1; i <= sizes[0]; i++)
                        for (int j = 0; j <= sizes[1]; j++)
                            for (int k = 0; k <= sizes[2]; k++) {
                                dp[i][j][k][s] += dp[i - 1][j][k][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            if (type == 1) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 0; i <= sizes[0]; i++)
                        for (int j = 1; j <= sizes[1]; j++)
                            for (int k = 0; k <= sizes[2]; k++) {
//                            System.out.println(i + " " + j + " " + k + " " + s + " " + dp.length + " " + dp[0].length + " " + dp[0][0].length + " " + dp[0][0][0].length);
                                dp[i][j][k][s] += dp[i][j - 1][k][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            if (type == 2) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 0; i <= sizes[0]; i++)
                        for (int j = 0; j <= sizes[1]; j++)
                            for (int k = 1; k <= sizes[2]; k++) {
//                            System.out.println(i + " " + j + " " + k + " " + s + " " + dp.length + " " + dp[0].length + " " + dp[0][0].length + " " + dp[0][0][0].length);
                                dp[i][j][k][s] += dp[i][j][k - 1][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            return sum + value;
        }

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int[][][][] ways = new int[MAXN][MAXN][MAXN][3];
            boolean[][][][] cached = new boolean[MAXN][MAXN][MAXN][3];
//        Arrays.fill(ways, -1);

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

            ArrayList<Integer>[] ar = new ArrayList[3];
            for (int i = 0; i < 3; i++) ar[i] = new ArrayList<Integer>();
            int total_sum = 0;
            for (int i = 0; i < n; i++) {
                int t = in.nextInt(), g = in.nextInt();
                ar[g - 1].add(t);
                total_sum += t;
            }

            if (T > total_sum) {
                out.println(0);
                return;
            }
            int min_index = 0, mn = 100000000;

            for (int i = 0; i < 3; i++) {
                if (ar[i].size() < mn) {
                    mn = ar[i].size();
                    min_index = i;
                }
            }

            int[][][][] dp = new int[ar[(1 + min_index) % 3].size() + 1][ar[(2 + min_index) % 3].size() + 1][1][total_sum + 1];
            int[][][][] dp2 = new int[1][1][mn + 1][total_sum + 1];
            dp[0][0][0][0] = dp2[0][0][0][0] = 1;
            int[] sizes = {0, 0, 0};
            int sum = 0;
            int[] order = {(min_index + 1) % 3, (min_index + 2) % 3};
            int type = 0;
            for (int i : order) {
                for (int v : ar[i])
                    sum = add(type, v, sizes, sum, dp);
                type++;
            }
            sum = 0;
            sizes[0] = sizes[1] = sizes[2] = 0;
            for (int i : ar[min_index])
                sum = add(2, i, sizes, sum, dp2);
            int[] factorial = new int[MAXN];
            factorial[0] = 1;
            for (int i = 1; i < MAXN; i++)
                factorial[i] = (int) ((factorial[i - 1] * 1L * i) % MOD);

            long answer = 0;
            for (int i = 0; i < dp.length; i++)
                for (int j = 0; j < dp[0].length; j++)
                    for (int k = 0; k <= mn; k++)
                        for (int s = 0; s <= T; s++) {

                            long x = (dp[i][j][0][s] * 1L * totalWays(i, j, k, ways, cached, factorial)) % MOD;
                            x *= dp2[0][0][k][T - s];
                            x %= MOD;
                            answer += x;

                        }
            out.println(answer % MOD);
        }

    }

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

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

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

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

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

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

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

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void println(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
            writer.print('\n');
        }

        public void close() {
            writer.close();
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;

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

    static class TaskG2 {
        static final int MOD = 1000000000 + 7;
        static final int MAXN = 51;

        int getWays(int i, int j, int k, int l, int[][][][] ways, boolean[][][][] cached) {
            if (i + j + k == 0) return l == -1 ? 1 : 0;
            if (l < 0) return 0;
            if (cached[i][j][k][l]) return ways[i][j][k][l];
            int s = i + j + k;
            long value = 0;
            if (l == 0 && i != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i - 1, j, k, x, ways, cached);
                    }
            }
            if (l == 1 && j != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i, j - 1, k, x, ways, cached);
                    }
            }
            if (l == 2 && k != 0) {
                for (int x = -1; x < 3; x++)
                    if (x != l) {
                        value += getWays(i, j, k - 1, x, ways, cached);
                    }
            }
            ways[i][j][k][l] = (int) (value % MOD);
            cached[i][j][k][l] = true;
            return ways[i][j][k][l];
        }

        int totalWays(int i, int j, int k, int[][][][] ways, boolean[][][][] cached, int[] factorial) {
            long ret = 0;
            for (int l = 0; l < 3; l++) ret += getWays(i, j, k, l, ways, cached);
            ret *= factorial[i];
            ret %= MOD;

            ret *= factorial[j];
            ret %= MOD;

            ret *= factorial[k];
            ret %= MOD;

            return (int) ret;
        }

        int add(int type, int value, int[] sizes, int sum, int[][][][] dp) {
            sizes[type]++;
            if (type == 0) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 1; i <= sizes[0]; i++)
                        for (int j = 0; j <= sizes[1]; j++)
                            for (int k = 0; k <= sizes[2]; k++) {
                                dp[i][j][k][s] += dp[i - 1][j][k][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            if (type == 1) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 0; i <= sizes[0]; i++)
                        for (int j = 1; j <= sizes[1]; j++)
                            for (int k = 0; k <= sizes[2]; k++) {
//                            System.out.println(i + " " + j + " " + k + " " + s + " " + dp.length + " " + dp[0].length + " " + dp[0][0].length + " " + dp[0][0][0].length);
                                dp[i][j][k][s] += dp[i][j - 1][k][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            if (type == 2) {
                for (int s = sum + value; s >= value; s--) {
                    for (int i = 0; i <= sizes[0]; i++)
                        for (int j = 0; j <= sizes[1]; j++)
                            for (int k = 1; k <= sizes[2]; k++) {
//                            System.out.println(i + " " + j + " " + k + " " + s + " " + dp.length + " " + dp[0].length + " " + dp[0][0].length + " " + dp[0][0][0].length);
                                dp[i][j][k][s] += dp[i][j][k - 1][s - value];
                                if (dp[i][j][k][s] >= MOD)
                                    dp[i][j][k][s] -= MOD;
                            }
                }
            }

            return sum + value;
        }

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int[][][][] ways = new int[MAXN][MAXN][MAXN][3];
            boolean[][][][] cached = new boolean[MAXN][MAXN][MAXN][3];
//        Arrays.fill(ways, -1);

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

            ArrayList<Integer>[] ar = new ArrayList[3];
            for (int i = 0; i < 3; i++) ar[i] = new ArrayList<Integer>();
            int total_sum = 0;
            for (int i = 0; i < n; i++) {
                int t = in.nextInt(), g = in.nextInt();
                ar[g - 1].add(t);
                total_sum += t;
            }

            if (T > total_sum) {
                out.println(0);
                return;
            }
            int min_index = 0, mn = 100000000;

            for (int i = 0; i < 3; i++) {
                if (ar[i].size() < mn) {
                    mn = ar[i].size();
                    min_index = i;
                }
            }

            int[][][][] dp = new int[ar[(1 + min_index) % 3].size() + 1][ar[(2 + min_index) % 3].size() + 1][mn + 1][total_sum + 1];
            dp[0][0][0][0] = 1;
            int[] sizes = {0, 0, 0};
            int sum = 0;
            int[] order = {(min_index + 1) % 3, (min_index + 2) % 3, min_index};
            int type = 0;
            for (int i : order) {
                for (int v : ar[i])
                    sum = add(type, v, sizes, sum, dp);
                type++;
            }
            int[] factorial = new int[MAXN];
            factorial[0] = 1;
            for (int i = 1; i < MAXN; i++)
                factorial[i] = (int) ((factorial[i - 1] * 1L * i) % MOD);
            long answer = 0;
            for (int i = 0; i < dp.length; i++)
                for (int j = 0; j < dp[0].length; j++)
                    for (int k = 0; k < dp[0][0].length; k++) {
                        answer += dp[i][j][k][T] * 1L * totalWays(i, j, k, ways, cached, factorial);
                        answer %= MOD;
                    }
            out.println(answer);
        }

    }

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

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

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

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

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

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

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

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void println(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
            writer.print('\n');
        }

        public void close() {
            writer.close();
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            G2PlaylistForPolycarpHardVersion solver = new G2PlaylistForPolycarpHardVersion();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class G2PlaylistForPolycarpHardVersion {
        Modular mod = new Modular(1e9 + 7);

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();
            int[][] musics = new int[n][2];
            int[] cnts = new int[4];
            for (int i = 0; i < n; i++) {
                musics[i][0] = in.readInt();
                musics[i][1] = in.readInt();
                cnts[musics[i][1]]++;
            }

            int c1 = cnts[1];
            int c2 = cnts[2];
            int c3 = cnts[3];

            int[][][][] comp = new int[c1 + 1][c2 + 1][c3 + 1][4];
            for (int i = 0; i <= c1; i++) {
                for (int j = 0; j <= c2; j++) {
                    for (int k = 0; k <= c3; k++) {
                        for (int t = 0; t < 4; t++) {
                            if (i == 0 && j == 0 && k == 0) {
                                comp[i][j][k][t] = 1;
                                continue;
                            }
                            if (i > 0 && t != 1) {
                                comp[i][j][k][t] = mod.plus(comp[i][j][k][t], mod.mul(comp[i - 1][j][k][1], i));
                            }
                            if (j > 0 && t != 2) {
                                comp[i][j][k][t] = mod.plus(comp[i][j][k][t], mod.mul(comp[i][j - 1][k][2], j));
                            }
                            if (k > 0 && t != 3) {
                                comp[i][j][k][t] = mod.plus(comp[i][j][k][t], mod.mul(comp[i][j][k - 1][3], k));
                            }
                        }
                    }
                }
            }

            int[][][][] last = new int[c1 + 1][c2 + 1][c3 + 1][m + 1];
            int[][][][] next = new int[c1 + 1][c2 + 1][c3 + 1][m + 1];

            last[0][0][0][0] = 1;
            int t1 = 0;
            int t2 = 0;
            int t3 = 0;
            for (int[] music : musics) {
                int m1 = music[1];
                int m0 = music[0];
                if (m1 == 1) {
                    t1++;
                } else if (m1 == 2) {
                    t2++;
                } else {
                    t3++;
                }
                for (int i = 0; i <= t1; i++) {
                    for (int j = 0; j <= t2; j++) {
                        for (int k = 0; k <= t3; k++) {
                            for (int t = 0; t <= m; t++) {
                                next[i][j][k][t] = last[i][j][k][t];
                                if (t < m0) {
                                    continue;
                                }
                                if (m1 == 1 && i > 0) {
                                    next[i][j][k][t] = mod.plus(next[i][j][k][t], last[i - 1][j][k][t - m0]);
                                } else if (m1 == 2 && j > 0) {
                                    next[i][j][k][t] = mod.plus(next[i][j][k][t], last[i][j - 1][k][t - m0]);
                                } else if (m1 == 3 && k > 0) {
                                    next[i][j][k][t] = mod.plus(next[i][j][k][t], last[i][j][k - 1][t - m0]);
                                }
                            }
                        }
                    }
                }

                int[][][][] tmp = last;
                last = next;
                next = tmp;
            }

            int ans = 0;
            for (int i = 0; i <= c1; i++) {
                for (int j = 0; j <= c2; j++) {
                    for (int k = 0; k <= c3; k++) {
                        ans = mod.plus(ans, mod.mul(last[i][j][k][m], comp[i][j][k][0]));
                    }
                }
            }

            out.println(ans);
        }

    }

    static class Modular {
        int m;

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

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

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

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

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                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;
        }

    }
}


//package prac;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class Round568G {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	//

	void solve()
	{
		int n = ni(), T = ni();
		int mod = 1000000007;
		int[][] a = new int[3][n];
		int[] ap = new int[3];
		for(int i = 0;i < n;i++){
			int t = ni();
			int k = ni()-1;
			a[k][ap[k]++] = t;
		}
		for(int i = 0;i < 3;i++)a[i] = Arrays.copyOf(a[i], ap[i]);

		long[][][][] com = new long[3][ap[0]+2][ap[1]+2][ap[2]+2];
		com[0][1][0][0] = com[1][0][1][0] = com[2][0][0][1] = 1;
		for(int i = 0;i <= ap[0];i++){
			for(int j = 0;j <= ap[1];j++){
				for(int k = 0;k <= ap[2];k++){
					for(int u = 0;u < 3;u++){
						if(u != 0){
							com[0][i+1][j][k] += com[u][i][j][k];
							if(com[0][i+1][j][k] >= mod)com[0][i+1][j][k] -= mod;
						}
						if(u != 1){
							com[1][i][j+1][k] += com[u][i][j][k];
							if(com[1][i][j+1][k] >= mod)com[1][i][j+1][k] -= mod;
						}
						if(u != 2){
							com[2][i][j][k+1] += com[u][i][j][k];
							if(com[2][i][j][k+1] >= mod)com[2][i][j][k+1] -= mod;
						}
					}
				}
			}
		}

		int[][] fif = enumFIF(200, mod);

		long[][][] dp = new long[3][][];
		for(int i = 0;i < 3;i++){
			int s = 0;
			for(int v : a[i])s += v;
			dp[i] = new long[ap[i]+1][s+1];
			dp[i][0][0] = 1;
			for(int v : a[i]){
				for(int j = ap[i]-1;j >= 0;j--){
					for(int k = s-v;k >= 0;k--){
						dp[i][j+1][k+v] += dp[i][j][k];
						if(dp[i][j+1][k+v] >= mod)dp[i][j+1][k+v] -= mod;
					}
				}
			}
		}

		long[][][] con = new long[ap[0]+1][ap[1]+1][2501];
		for(int i = 0;i <= ap[0];i++){
			for(int j = 0;j <= ap[1];j++){
				for(int k = 0;k < dp[0][i].length;k++){
					if(dp[0][i][k] == 0)continue;
					for(int l = 0;l < dp[1][j].length;l++){
						con[i][j][k+l] += dp[0][i][k] * dp[1][j][l];
						con[i][j][k+l] %= mod;
					}
				}
			}
		}

		long ans = 0;
		for(int i = 0;i <= ap[0];i++){
			for(int j = 0;j <= ap[1];j++){
				for(int k = 0;k <= ap[2];k++){
					long base = (com[0][i][j][k] + com[1][i][j][k] + com[2][i][j][k]) * fif[0][i] % mod * fif[0][j] % mod *
							fif[0][k] % mod;
					long ls = 0;
					for(int l = 0;l <= T;l++){
						if(T-l < dp[2][k].length){
							ls += con[i][j][l] * dp[2][k][T-l];
							ls %= mod;
						}
					}
//					if(base > 0 && ls > 0){
//						tr(i, j, k, base, ls);
//					}
					ans += base * ls;
					ans %= mod;
				}
			}
		}
		out.println(ans);
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][] { f, invf };
	}

	void run() throws Exception
	{
//		int n = 50, m = 2500;
//		Random gen = new Random();
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		sb.append(m + " ");
//		for (int i = 0; i < n; i++) {
//			sb.append(50 + " ");
//			sb.append(gen.nextInt(3)+1 + " ");
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new Round568G().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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

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


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

public class B {

	static int n, t[], g[], MOD = (int) 1e9 + 7;
	static int[][][] memo1, memo2[], memo3[];

	static int dp1(int idx, int remCnt, int remSum) {
		if (idx == n)
			return remSum == 0 && remCnt == 0 ? 1 : 0;
		if (remCnt < 0 || remSum < 0)
			return 0;
		if (memo1[idx][remCnt][remSum] != -1)
			return memo1[idx][remCnt][remSum];
		int ans = dp1(idx + 1, remCnt, remSum);
		if (g[idx] == 0) {
			ans += dp1(idx + 1, remCnt - 1, remSum - t[idx]);
			if (ans >= MOD)
				ans -= MOD;
		}
		return memo1[idx][remCnt][remSum] = ans;
	}

	static int dp2(int idx, int remCnt1, int remCnt2, int remSum) {

		if (idx == n)
			return remSum == 0 && remCnt1 == 0 && remCnt2 == 0 ? 1 : 0;
		if (remSum < 0 || remCnt1 < 0 || remCnt2 < 0)
			return 0;
		if (memo2[idx][remCnt1][remCnt2][remSum] != -1)
			return memo2[idx][remCnt1][remCnt2][remSum];
		int ans = dp2(idx + 1, remCnt1, remCnt2, remSum);

		if (g[idx] == 1)
			ans += dp2(idx + 1, remCnt1 - 1, remCnt2, remSum - t[idx]);
		else if (g[idx] == 2)
			ans += dp2(idx + 1, remCnt1, remCnt2 - 1, remSum - t[idx]);

		return memo2[idx][remCnt1][remCnt2][remSum] = ans;
	}

	private static int dp3(int cnt0, int cnt1, int cnt2, int last) {
		if (cnt0 + cnt1 + cnt2 == 0)
			return 1;
		if (memo3[last][cnt0][cnt1][cnt2] != -1)
			return memo3[last][cnt0][cnt1][cnt2];
		long ans = 0;
		if (cnt0 > 0 && last != 0)
			ans += dp3(cnt0 - 1, cnt1, cnt2, 0);
		if (cnt1 > 0 && last != 1)
			ans += dp3(cnt0, cnt1 - 1, cnt2, 1);
		if (cnt2 > 0 && last != 2)
			ans += dp3(cnt0, cnt1, cnt2 - 1, 2);
		return memo3[last][cnt0][cnt1][cnt2] = (int) (ans % MOD);

	}

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n = sc.nextInt();
		int[] fac = new int[n + 1];
		t = new int[n];
		g = new int[n];
		int[] cnt = new int[3];
		fac[0] = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = (int) (i * 1L * fac[i - 1] % MOD);
		int T = sc.nextInt();
		for (int i = 0; i < n; i++) {
			t[i] = sc.nextInt();
			g[i] = sc.nextInt() - 1;
			cnt[g[i]]++;

		}
		memo1 = new int[n][cnt[0] + 1][T + 1];
		memo2 = new int[n][cnt[1] + 1][cnt[2] + 1][T + 1];
		memo3 = new int[4][cnt[0] + 1][cnt[1] + 1][cnt[2] + 1];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= cnt[0]; j++)
				Arrays.fill(memo1[i][j], -1);
			for (int j = 0; j <= cnt[1]; j++)
				for (int k = 0; k <= cnt[2]; k++)
					Arrays.fill(memo2[i][j][k], -1);

		}
		for (int i = 0; i < 4; i++)
			for (int j = 0; j <= cnt[0]; j++)
				for (int k = 0; k <= cnt[1]; k++)
					Arrays.fill(memo3[i][j][k], -1);
		int ans = 0;
		for (int cnt0 = 0; cnt0 <= cnt[0]; cnt0++)
			for (int sum0 = 0; sum0 <= T; sum0++)
				for (int cnt1 = 0; cnt1 <= cnt[1]; cnt1++)
					for (int cnt2 = 0; cnt2 <= cnt[2]; cnt2++) {
						long ways = dp1(0, cnt0, sum0) * 1L * dp2(0, cnt1, cnt2, T - sum0) % MOD;
						ways = ways * dp3(cnt0, cnt1, cnt2, 3) % MOD;
						ways *= fac[cnt0];
						ways %= MOD;
						ways *= fac[cnt1];
						ways %= MOD;
						ways *= fac[cnt2];
						ways %= MOD;
						ans += ways;
						if (ans >= MOD)
							ans -= MOD;
					}
		out.println(ans);
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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

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

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

	}

}


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

import java.math.*;
import java.awt.Point;

public class CFTemplate {
    static final long MOD = 1000000007L;
    //static final long MOD2 = 1000000009L;
    //static final long MOD = 998244353L;
    //static final long INF = 500000000000L;
    static final int INF = 1100000000;
    static final int NINF = -100000;
    static FastScanner sc;
    static PrintWriter pw;
    static final int[][] dirs = {{-1,0},{1,0},{0,-1},{0,1}};

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

        ArrayList<Integer> primes = new ArrayList<Integer>();
        for (int i = 2; i <= 3200; i++) {
            boolean p = true;
            for (int j = 2; j*j <= i; j++) {
                if (i%j==0) {
                    p = false;
                    break;
                }
            }
            if (p) primes.add(i);
        }
        int Q = sc.ni();
        for (int q = 0; q < Q; q++) {
            int N = sc.ni();
            int K = sc.ni();
            int[] nums = new int[N+1];
            for (int i = 1; i <= N; i++) nums[i] = sc.ni();
            for (int i = 1; i <= N; i++) {
                for (int p: primes) {
                    int c = 0;
                    while (nums[i] % p == 0) {
                        nums[i] /= p;
                        c++;
                    }
                    if (c%2==1) nums[i] *= p;
                }
            }

            TreeSet<Integer> ts = new TreeSet<Integer>();
            HashMap<Integer,Integer> last = new HashMap<Integer,Integer>();

            int[][] dp = new int[N+1][K+1];
            for (int i = 1; i <= N; i++) {
                if (last.containsKey(nums[i])) {
                    ts.add(last.get(nums[i]));
                }
                last.put(nums[i],i);
                int[] inds = new int[K+1];
                int ind = 0;
                for (int x: ts.descendingSet()) {
                    inds[ind] = x;
                    if (ind==K) break;
                    ind++;
                }
                for (int j = 0; j <= K; j++) {
                    dp[i][j] = INF;
                    if (j > 0) dp[i][j] = dp[i][j-1];
                    for (int k = 0; k <= j; k++) {
                        dp[i][j] = Math.min(dp[i][j],dp[inds[k]][j-k]+1);
                    }
                }
            }
            pw.println(dp[N][K]);
        }
        pw.close();
    }

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

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

    //Sort an array (immune to quicksort TLE)
    public static void sort(int[][] arr) {
        Random rgen = new Random();
        for (int i = 0; i < arr.length; i++) {
            int r = rgen.nextInt(arr.length);
            int[] temp = arr[i];
            arr[i] = arr[r];
            arr[r] = temp;
        }
        Arrays.sort(arr, new Comparator<int[]>() {
            @Override
            public int compare(int[] a, int[] b) {
                return a[1]-b[1];
                //Ascending order.
            }
        });
    }

    public static void sort(long[][] arr) {
        Random rgen = new Random();
        for (int i = 0; i < arr.length; i++) {
            int r = rgen.nextInt(arr.length);
            long[] temp = arr[i];
            arr[i] = arr[r];
            arr[r] = temp;
        }
        Arrays.sort(arr, new Comparator<long[]>() {
            @Override
            public int compare(long[] a, long[] b) {
                if (a[0] > b[0])
                    return 1;
                else if (a[0] < b[0])
                    return -1;
                else
                    return 0;
                //Ascending order.
            }
        });
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in), 32768);
            st = null;
        }

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

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

        int[][] graph(int N, int[][] edges) {
            int[][] graph = new int[N][];
            int[] sz = new int[N];
            for (int[] e: edges) {
                sz[e[0]] += 1;
                sz[e[1]] += 1;
            }
            for (int i = 0; i < N; i++) {
                graph[i] = new int[sz[i]];
            }
            int[] cur = new int[N];
            for (int[] e: edges) {
                graph[e[0]][cur[e[0]]] = e[1];
                graph[e[1]][cur[e[1]]] = e[0];
                cur[e[0]] += 1;
                cur[e[1]] += 1;
            }
            return graph;
        }

        int[] intArray(int N, int mod) {
            int[] ret = new int[N];
            for (int i = 0; i < N; i++)
                ret[i] = ni()+mod;
            return ret;
        }

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

        long[] longArray(int N, long mod) {
            long[] ret = new long[N];
            for (int i = 0; i < N; i++)
                ret[i] = nl()+mod;
            return ret;
        }

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

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


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

public class Solve{
    public static void main(String[] args) throws Exception{
        Scanner sc=new Scanner(System.in);
        PrintWriter out =new PrintWriter(System.out);
        int size=(int)1e7+1;
        int[] pr=new int[size];
        for(int i=0;i<size;i++){
            pr[i]=i;
        }
        for(int i=2;i*i<size;i++){
          int val=i*i;
            for(int j=val;j<=size;j+=val){
                 pr[j]=j/val;
            }
        }
        int t=sc.nextInt();
        int[] dp=new int[size];
        Arrays.fill(dp,-1);
        while(t-->0){
            int n=sc.nextInt();
            int k=sc.nextInt();
            int[] ar=new int[n];
            for(int i=0;i<n;i++){
                int a=sc.nextInt();
                ar[i]=pr[a];
            }
            int[] ans=new int[k+1];
            int[] ind=new int[k+1];
            for(int i=0;i<n;i++){
                for(int h=k;h>=0;h--){
                    if(dp[ar[i]]>=ind[h]){
                        ans[h]++;
                        ind[h]=i;
                    }
                    if(h>0 && (ans[h-1]<ans[h] ||(ans[h-1]==ans[h] && ind[h-1]>ind[h])))
                    {
                        ans[h]=ans[h-1];
                        ind[h]=ind[h-1];
                    }
                }
                dp[ar[i]]=i;
            }
            out.println(ans[k]+1);
            for(int i=0;i<n;i++)dp[ar[i]]=-1;
        }
        out.close();
    }
}


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

public class E2 {
    static ArrayList<Integer> primes;
    static int[] mind;
    final static int MAXA = (int) 1e7;

    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int t = Integer.parseInt(st.nextToken());
        primes = new ArrayList<>();
        mind = new int[MAXA + 1];
        for (int i = 2; i <= MAXA; i++) {
            if (mind[i] == 0) {
                primes.add(i);
                mind[i] = i;
            }
            for (int x : primes) {
                if (x > mind[i] || x * i > MAXA) break;
                mind[x * i] = x;
            }
        }
        int[] count = new int[MAXA + 1];
        for (int on8y = 0; on8y < t; on8y++) {
            st = new StringTokenizer(f.readLine());
            int n = Integer.parseInt(st.nextToken());
            int k = Integer.parseInt(st.nextToken());
            int[] a = new int[n];
            Arrays.fill(a, 1);
            st = new StringTokenizer(f.readLine());
            for (int i = 0; i < n; i++) {
                int x = Integer.parseInt(st.nextToken());
                int cnt = 0;
                int last = 0;
                while (x > 1) {
                    int p = mind[x];
                    if (last == p) cnt++;
                    else {
                        if (cnt % 2 == 1) a[i] *= last;
                        last = p;
                        cnt = 1;
                    }
                    x /= p;
                }
                if (cnt % 2 == 1) a[i] *= last;
            }
            int[][] mnleft = new int[n][k + 1];
            for (int j = 0; j < k + 1; j++) {
                int l = n;
                int now = 0;
                for (int i = n - 1; i >= 0; i--) {
                    while (l - 1 >= 0 && now + ((count[a[l - 1]] > 0) ? 1 : 0) <= j) {
                        l--;
                        now += (count[a[l]] > 0) ? 1 : 0;
                        count[a[l]]++;
                    }
                    mnleft[i][j] = l;
                    if (count[a[i]] > 1) now--;
                    count[a[i]]--;
                }
            }
            int[][] dp = new int[n + 1][k + 1];
            for (int i = 0; i < n + 1; i++) {
                Arrays.fill(dp[i], (int) 1e9 + 1);
            }
            for (int i = 0; i < k + 1; i++) dp[0][i] = 0;
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= k; j++) {
                    if (j > 0) dp[i][j] = dp[i][j - 1];
                    for (int lst = 0; lst <= j; lst++) {
                        dp[i][j] = Math.min(dp[i][j], dp[mnleft[i - 1][lst]][j - lst] + 1);
                    }
                }
            }
            int ans = (int) 1e9 + 1;
            for (int c : dp[n]) ans = Math.min(ans, c);
            System.out.println(ans);

        }
    }
}


// https://codeforces.com/contest/1497/submission/110250082
import java.io.*;
import java.util.*;

public class CF1497E2 extends PrintWriter {
	CF1497E2() { super(System.out); }
	static class Scanner {
		Scanner(InputStream in) { this.in = in; } InputStream in;
		byte[] bb = new byte[1 << 15]; int i, n;
		byte getc() {
			if (i == n) {
				i = n = 0;
				try { n = in.read(bb); } catch (IOException e) {}
			}
			return i < n ? bb[i++] : 0;
		}
		int nextInt() {
			byte c = 0; while (c <= ' ') c = getc();
			int a = 0; while (c > ' ') { a = a * 10 + c - '0'; c = getc(); }
			return a;
		}
	}
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1497E2 o = new CF1497E2(); o.main(); o.flush();
	}

	static final int A = 10000000, K = 20;
	int[] cc = new int[A + 1]; {
		for (int a = 1; a <= A; a++)
			cc[a] = a;
		for (int a = 2; a <= A / a; a++) {
			int s = a * a;
			for (int b = s; b <= A; b += s)
				while (cc[b] % s == 0)
					cc[b] /= s;
		}
	}
	void main() {
		int[] pp = new int[A + 1]; Arrays.fill(pp, -1);
		int t = sc.nextInt();
		while (t-- > 0) {
			int n = sc.nextInt();
			int k = sc.nextInt();
			int[] aa = new int[n];
			for (int i = 0; i < n; i++)
				aa[i] = cc[sc.nextInt()];
			int[] mp = new int[k + 1];
			int[] ip = new int[k + 1];
			for (int i = 0; i < n; i++) {
				int a = aa[i];
				for (int h = k; h >= 0; h--) {
					if (pp[a] >= ip[h]) {
						mp[h]++;
						ip[h] = i;
					}
					if (h > 0 && (mp[h - 1] < mp[h] || mp[h - 1] == mp[h] && ip[h - 1] > ip[h])) {
						mp[h] = mp[h - 1];
						ip[h] = ip[h - 1];
					}
				}
				pp[a] = i;
			}
			println(mp[k] + 1);
			for (int i = 0; i < n; i++) {
				int a = aa[i];
				pp[a] = -1;
			}
		}
	}
}