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

public class C {

    static int SIZE = 62; // sub2: 16, sub3: 32, sub4: 62
    static long MOD = 998244353;

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(in.readLine());
        long[][][] words = new long[11][SIZE][SIZE];
        TreeSet<String> ts = new TreeSet<String>();
        for(int n = 0; n < N; n++) {
            String w = in.readLine();
            if(ts.contains(reverse(w))) continue;
            ts.add(w);
            int a = charToInt(w.charAt(0));
            int b = charToInt(w.charAt(w.length()-1));
            words[w.length()][a][b]++;
            if(!isPal(w)) words[w.length()][b][a]++;
        }

        long sum = 0;

        for(int LEN = 3; LEN <= 10; LEN++) {
            long[][][] dyn = new long[SIZE][SIZE][SIZE];
            for(int a = 0; a < SIZE; a++) {
                for(int b = 0; b < SIZE; b++) {
                    for(int c = 0; c < SIZE; c++) {
                        for(int x = 0; x < SIZE; x++) {
                            long add = (words[LEN][a][x]*words[LEN][b][x])%MOD;
                            add = (add*words[LEN][c][x])%MOD;
                            dyn[a][b][c] += add;
                            dyn[a][b][c] %= MOD;
                        }}}}
            for(int a = 0; a < SIZE; a++) {
                for(int b = 0; b < SIZE; b++) {
                    for(int c = 0; c < SIZE; c++) {
                        for(int d = 0; d < SIZE; d++) {
                            long add = (dyn[a][b][c]*dyn[b][c][d])%MOD;
                            add *= (dyn[a][c][d]*dyn[a][b][d])%MOD;
                            add %= MOD;
                            sum += add;
                            sum %= MOD;
                        }}}}

        }

        System.out.println(sum);

        in.close();
    }

    static int charToInt(char c) {
        if('a' <= c && c <= 'z')
            return c-'a';
        else if('A' <= c && c <= 'Z')
            return (SIZE==62 ? 26 : 16) + c-'A';
        else
            return 10+26+c-'a';
    }

    static boolean isPal(String s) {
        int n = s.length();
        for(int i = 0; i <= n/2; i++)
            if(s.charAt(i) != s.charAt(n-1-i))
                return false;
        return true;
    }

    static String reverse(String s) {
        StringBuilder sb = new StringBuilder();
        for(int i = s.length()-1; i >= 0; i--)
            sb.append(s.charAt(i));
        return sb.toString();
    }
}


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

public class C {

    static int SIZE = 62; // sub2: 16, sub3: 32, sub4: 62
    static long MOD = 998244353;

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(in.readLine());
        long[][][] words = new long[11][SIZE][SIZE];
        TreeSet<String> ts = new TreeSet<String>();
        for(int n = 0; n < N; n++) {
            String w = in.readLine();
            if(ts.contains(reverse(w))) continue;
            ts.add(w);
            int a = charToInt(w.charAt(0));
            int b = charToInt(w.charAt(w.length()-1));
            words[w.length()][a][b]++;
            if(!isPal(w)) words[w.length()][b][a]++;
        }

        long sum = 0;

        for(int LEN = 3; LEN <= 10; LEN++) {
            long[][][] dyn = new long[SIZE][SIZE][SIZE];
            for(int a = 0; a < SIZE; a++) {
                for(int b = a; b < SIZE; b++) {
                    for(int c = b; c < SIZE; c++) {
                        for(int x = 0; x < SIZE; x++) {
                            long add = (words[LEN][a][x]*words[LEN][b][x])%MOD;
                            add = (add*words[LEN][c][x])%MOD;
                            dyn[a][b][c] += add;
                            dyn[a][b][c] %= MOD;
                        }
                        dyn[a][c][b] = dyn[a][b][c];
                        dyn[b][a][c] = dyn[a][b][c];
                        dyn[b][c][a] = dyn[a][b][c];
                        dyn[c][a][b] = dyn[a][b][c];
                        dyn[c][b][a] = dyn[a][b][c];
                    }}}
            for(int a = 0; a < SIZE; a++) {
                for(int b = a; b < SIZE; b++) {
                    for(int c = b; c < SIZE; c++) {
                        for(int d = c; d < SIZE; d++) {
                            long add = (dyn[a][b][c]*dyn[b][c][d])%MOD;
                            add *= (dyn[a][c][d]*dyn[a][b][d])%MOD;
                            add %= MOD;
                            //if(add > 0) {
                            //    System.err.print(a+", "+b+", "+c+", "+d+"  ");
                            //    System.err.print(add+" -> ");
                            //}
                            if(a == b && b == c && c == d)
                                add *= 1;
                            else if((a == b && b == c) || // d
                                    (a == b && b == d) || // c
                                    (a == c && c == d) || // b
                                    (b == c && c == d))   // a
                                add *= 4;
                            else if(a == b && c == d)
                                add *= 6;
                            else if(a == b || b == c || c == d)
                                    add *= 12;
                            else
                                add *= 24;
                            //if(add > 0)
                            //    System.err.println(add);
                            sum += add;
                            sum %= MOD;
                        }}}}

        }

        System.out.println(sum);

        in.close();
    }

    static int charToInt(char c) {
        if('a' <= c && c <= 'z')
            return c-'a';
        else if('A' <= c && c <= 'Z')
            return (SIZE==62 ? 26 : 16) + c-'A';
        else
            return 2*26+c-'0';
    }

    static boolean isPal(String s) {
        int n = s.length();
        for(int i = 0; i <= n/2; i++)
            if(s.charAt(i) != s.charAt(n-1-i))
                return false;
        return true;
    }

    static String reverse(String s) {
        StringBuilder sb = new StringBuilder();
        for(int i = s.length()-1; i >= 0; i--)
            sb.append(s.charAt(i));
        return sb.toString();
    }
}


import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class F {

	static void sortBy(int a[], int n, long v[]) {
		if (n == 0) {
			return;
		}
		for (int i = 1; i < n; i++) {
			int j = i;
			int ca = a[i];
			long cv = v[ca];
			do {
				int nj = (j - 1) >> 1;
				int na = a[nj];
				if (cv <= v[na]) {
					break;
				}
				a[j] = na;
				j = nj;
			} while (j != 0);
			a[j] = ca;
		}
		int ca = a[0];
		for (int i = n - 1; i > 0; i--) {
			int j = 0;
			while ((j << 1) + 2 + Integer.MIN_VALUE < i + Integer.MIN_VALUE) {
				j <<= 1;
				j += (v[a[j + 2]] > v[a[j + 1]]) ? 2 : 1;
			}
			if ((j << 1) + 2 == i) {
				j = (j << 1) + 1;
			}
			int na = a[i];
			a[i] = ca;
			ca = na;
			long cv = v[ca];
			while (j != 0 && v[a[j]] < cv) {
				j = (j - 1) >> 1;
			}
			while (j != 0) {
				na = a[j];
				a[j] = ca;
				ca = na;
				j = (j - 1) >> 1;
			}
		}
		a[0] = ca;
	}

	static final long MUL_BIT_TABLE[] = new long[64 * 64];
	static long mulBits(int i, int j) {
		int key = i * 64 + j;
		long res = MUL_BIT_TABLE[key];
		if (res == 0) {
			res = 1;
			for (int k = 5; k >= 0; k--) {
				if (((i ^ j) & (1 << k)) != 0) {
					res <<= 1 << k;
				}
			}
			for (int k = 5; k >= 0; k--) {
				if ((i & j & (1 << k)) != 0) {
					res = mul(res, 3L << ((1 << k) - 1));
				}
			}
			MUL_BIT_TABLE[key] = res;
		}
		return res;
	}

	static long mulSlow(long a, long b) {
		long res = 0;
		for (int i = 0; i < 64; i++) {
			if ((a & (1L << i)) == 0) {
				continue;
			}
			for (int j = 0; j < 64; j++) {
				if ((b & (1L << j)) == 0) {
					continue;
				}
				res ^= mulBits(i, j);
			}
		}
		return res;
	}

	static long mulCached(int i, int vi, int j, int vj) {
		int key = ((i * 8 + j) * 256 + vi) * 256 + vj;
		long res = MUL_TABLE[key];
		if (res == 0) {
			if ((vi & 0xf) != 0 && (vi & 0xf0) != 0) {
				res = mulCached(i, vi & 0xf, j, vj) ^ mulCached(i, vi & 0xf0, j, vj);
			} else if ((vj & 0xf) != 0 && (vj & 0xf0) != 0) {
				res = mulCached(i, vi, j, vj & 0xf) ^ mulCached(i, vi, j, vj & 0xf0);
			} else {
				res = mulSlow((long) vi << (8 * i), (long) vj << (8 * j));
			}
			MUL_TABLE[key] = res;
		}
		return res;
	}

	static final long MUL_TABLE[] = new long[8 * 8 * 256 * 256];
	static long mul(long a, long b) {
		long res = 0;
		for (int i = 0; i < 8; i++) {
			int vi = (int) ((a >> (8 * i)) & 255);
			if (vi == 0) {
				continue;
			}
			for (int j = 0; j < 8; j++) {
				int vj = (int) ((b >> (8 * j)) & 255);
				if (vj == 0) {
					continue;
				}
				res ^= mulCached(i, vi, j, vj);
			}
		}
		return res;
	}

	static long pow(long a, long e) {
		if (e == 0) {
			return 1;
		}
		long r = a;
		for (int i = 62 - Long.numberOfLeadingZeros(e); i >= 0; i--) {
			r = mul(r, r);
			if ((e & (1L << i)) != 0) {
				r = mul(r, a);
			}
		}
		return r;
	}

	static final long PRE_TABLE[] = new long[16 * 16];
	static void preClear() {
		fill(PRE_TABLE, 0);
	}
	static long preMul(long a, long b) {
		long res = 0;
		for (int i = 0; i < 16; i++) {
			int vi = (int) ((a >> (4 * i)) & 15);
			if (vi == 0) {
				continue;
			}
			int pkey = i * 16 + vi;
			long pres = PRE_TABLE[pkey];
			if (pres == 0) {
				int ii = i >> 1, vii = (i & 1) == 0 ? vi : vi << 4;
				for (int j = 0; j < 8; j++) {
					int vj = (int) ((b >> (8 * j)) & 255);
					if (vj == 0) {
						continue;
					}
					pres ^= mulCached(ii, vii, j, vj);
				}
				PRE_TABLE[pkey] = pres;
			}
			res ^= pres;
		}
		return res;
	}

	static final long GEN = -Long.MAX_VALUE;
	static final int PRIMES[] = {3, 5, 17, 257, 641, 65537, 6700417};
	static final int PRIME_STEP[] = {1, 1, 1, 1, 1, 20, 200};
	static final long POW_VALS[][] = new long[PRIMES.length][];
	static final int POW_IDX[][] = new int[PRIMES.length][];
	static {
		for (int i = 0; i < PRIMES.length; i++) {
			int p = PRIMES[i];
			int s = PRIME_STEP[i];
			int l = p / s;
			POW_VALS[i] = new long[l];
			POW_IDX[i] = new int[l];
			POW_VALS[i][0] = 1;
			long cgen = pow(GEN, Long.divideUnsigned(-1, p) * s);
			preClear();
			for (int j = 1; j < l; j++) {
				POW_VALS[i][j] = preMul(POW_VALS[i][j - 1], cgen);
				POW_IDX[i][j] = j;
			}
			sortBy(POW_IDX[i], l, POW_VALS[i]);
		}
	}

	static final BigInteger bMod = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE);

	static BigInteger dlog(long v) {
		BigInteger res = BigInteger.ZERO;
		for (int i = 0; i < PRIMES.length; i++) {
			int p = PRIMES[i];
			int s = PRIME_STEP[i];
			int len = p / s;
			long vv = pow(v, Long.divideUnsigned(-1, p));
			long cgen = pow(GEN, -1 - Long.divideUnsigned(-1, p));
			int cres = -1;
			preClear();
			for (int j = 0; j < s; j++) {
				int l = 0, r = len;
				while (l < r) {
					int mid = (l + r) >> 1;
					if (POW_VALS[i][POW_IDX[i][mid]] < vv) {
						l = mid + 1;
					} else {
						r = mid;
					}
				}
				if (l < len && POW_VALS[i][POW_IDX[i][l]] == vv) {
					cres = POW_IDX[i][l] * s + j;
					break;
				}
				vv = preMul(vv, cgen);
			}
			BigInteger bp = BigInteger.valueOf(p);
			BigInteger md = bMod.divide(bp);
			res = res.add(md.modInverse(bp).multiply(md).multiply(BigInteger.valueOf(cres)));
		}
		return res.mod(bMod);
	}

	static void solve() throws Exception {
		int tests = scanInt();
//		int tests = 100;
		for (int test = 0; test < tests; test++) {
			long a = new BigInteger(scanString()).longValue(),
			     b = new BigInteger(scanString()).longValue();
//			long a = test * 12345678901L + 12345678901234567L, b = pow(a, 1999);
			BigInteger logA = dlog(a), logB = dlog(b);
			BigInteger x;
			if (logB.signum() == 0) {
				x = BigInteger.ZERO;
			} else {
				BigInteger gcd = logA.gcd(logB).gcd(bMod);
				logA = logA.divide(gcd);
				logB = logB.divide(gcd);
				BigInteger curMod = bMod.divide(gcd);
				if (logA.gcd(curMod).compareTo(BigInteger.ONE) != 0) {
					x = BigInteger.ONE.negate();
				} else {
					x = logA.modInverse(curMod).multiply(logB).mod(curMod);
				}
			}
			out.println(x);
		}
	}

	static int scanInt() throws IOException {
		return parseInt(scanString());
	}

	static long scanLong() throws IOException {
		return parseLong(scanString());
	}

	static String scanString() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class F {

	static void sortBy(int a[], int n, long v[]) {
		if (n == 0) {
			return;
		}
		for (int i = 1; i < n; i++) {
			int j = i;
			int ca = a[i];
			long cv = v[ca];
			do {
				int nj = (j - 1) >> 1;
				int na = a[nj];
				if (cv <= v[na]) {
					break;
				}
				a[j] = na;
				j = nj;
			} while (j != 0);
			a[j] = ca;
		}
		int ca = a[0];
		for (int i = n - 1; i > 0; i--) {
			int j = 0;
			while ((j << 1) + 2 + Integer.MIN_VALUE < i + Integer.MIN_VALUE) {
				j <<= 1;
				j += (v[a[j + 2]] > v[a[j + 1]]) ? 2 : 1;
			}
			if ((j << 1) + 2 == i) {
				j = (j << 1) + 1;
			}
			int na = a[i];
			a[i] = ca;
			ca = na;
			long cv = v[ca];
			while (j != 0 && v[a[j]] < cv) {
				j = (j - 1) >> 1;
			}
			while (j != 0) {
				na = a[j];
				a[j] = ca;
				ca = na;
				j = (j - 1) >> 1;
			}
		}
		a[0] = ca;
	}

	static final long MUL_BIT_TABLE[] = new long[64 * 64];
	static long mulBits(int i, int j) {
		int key = i * 64 + j;
		long res = MUL_BIT_TABLE[key];
		if (res == 0) {
			res = 1;
			for (int k = 5; k >= 0; k--) {
				if (((i ^ j) & (1 << k)) != 0) {
					res <<= 1 << k;
				}
			}
			for (int k = 5; k >= 0; k--) {
				if ((i & j & (1 << k)) != 0) {
					res = mul(res, 3L << ((1 << k) - 1));
				}
			}
			MUL_BIT_TABLE[key] = res;
		}
		return res;
	}

	static long mulSlow(long a, long b) {
		long res = 0;
		for (int i = 0; i < 64; i++) {
			if ((a & (1L << i)) == 0) {
				continue;
			}
			for (int j = 0; j < 64; j++) {
				if ((b & (1L << j)) == 0) {
					continue;
				}
				res ^= mulBits(i, j);
			}
		}
		return res;
	}

	static long mulCached(int i, int vi, int j, int vj) {
		int key = ((i * 8 + j) * 256 + vi) * 256 + vj;
		long res = MUL_TABLE[key];
		if (res == 0) {
			if ((vi & 0xf) != 0 && (vi & 0xf0) != 0) {
				res = mulCached(i, vi & 0xf, j, vj) ^ mulCached(i, vi & 0xf0, j, vj);
			} else if ((vj & 0xf) != 0 && (vj & 0xf0) != 0) {
				res = mulCached(i, vi, j, vj & 0xf) ^ mulCached(i, vi, j, vj & 0xf0);
			} else {
				res = mulSlow((long) vi << (8 * i), (long) vj << (8 * j));
			}
			MUL_TABLE[key] = res;
		}
		return res;
	}

	static final long MUL_TABLE[] = new long[8 * 8 * 256 * 256];
	static long mul(long a, long b) {
		long res = 0;
		for (int i = 0; i < 8; i++) {
			int vi = (int) ((a >> (8 * i)) & 255);
			if (vi == 0) {
				continue;
			}
			for (int j = 0; j < 8; j++) {
				int vj = (int) ((b >> (8 * j)) & 255);
				if (vj == 0) {
					continue;
				}
				res ^= mulCached(i, vi, j, vj);
			}
		}
		return res;
	}

	static long pow(long a, long e) {
		if (e == 0) {
			return 1;
		}
		long r = a;
		for (int i = 62 - Long.numberOfLeadingZeros(e); i >= 0; i--) {
			r = mul(r, r);
			if ((e & (1L << i)) != 0) {
				r = mul(r, a);
			}
		}
		return r;
	}

	static final long PRE_TABLE[] = new long[16 * 16];
	static void preClear() {
		fill(PRE_TABLE, 0);
	}
	static long preMul(long a, long b) {
		long res = 0;
		for (int i = 0; i < 16; i++) {
			int vi = (int) ((a >> (4 * i)) & 15);
			if (vi == 0) {
				continue;
			}
			int pkey = i * 16 + vi;
			long pres = PRE_TABLE[pkey];
			if (pres == 0) {
				int ii = i >> 1, vii = (i & 1) == 0 ? vi : vi << 4;
				for (int j = 0; j < 8; j++) {
					int vj = (int) ((b >> (8 * j)) & 255);
					if (vj == 0) {
						continue;
					}
					pres ^= mulCached(ii, vii, j, vj);
				}
				PRE_TABLE[pkey] = pres;
			}
			res ^= pres;
		}
		return res;
	}

	static final long GEN = -Long.MAX_VALUE;
	static final int PRIMES[] = {3, 5, 17, 257, 641, 65537, 6700417};
	static final int PRIME_STEP[] = {1, 1, 1, 1, 1, 20, 200};
	static final long POW_VALS[][] = new long[PRIMES.length][];
	static final int POW_IDX[][] = new int[PRIMES.length][];
	static {
		for (int i = 0; i < PRIMES.length; i++) {
			int p = PRIMES[i];
			int s = PRIME_STEP[i];
			int l = (p + s - 1) / s;
			POW_VALS[i] = new long[l];
			POW_IDX[i] = new int[l];
			POW_VALS[i][0] = 1;
			long cgen = pow(GEN, Long.divideUnsigned(-1, p) * s);
			preClear();
			for (int j = 1; j < l; j++) {
				POW_VALS[i][j] = preMul(POW_VALS[i][j - 1], cgen);
				POW_IDX[i][j] = j;
			}
			sortBy(POW_IDX[i], l, POW_VALS[i]);
		}
	}

	static final BigInteger bMod = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE);

	static BigInteger dlog(long v) {
		BigInteger res = BigInteger.ZERO;
		for (int i = 0; i < PRIMES.length; i++) {
			int p = PRIMES[i];
			int s = PRIME_STEP[i];
			int len = POW_VALS[i].length;
			long vv = pow(v, Long.divideUnsigned(-1, p));
			long cgen = pow(GEN, -1 - Long.divideUnsigned(-1, p));
			int cres = -1;
			preClear();
			for (int j = 0; j < s; j++) {
				int l = 0, r = len;
				while (l < r) {
					int mid = (l + r) >> 1;
					if (POW_VALS[i][POW_IDX[i][mid]] < vv) {
						l = mid + 1;
					} else {
						r = mid;
					}
				}
				if (l < len && POW_VALS[i][POW_IDX[i][l]] == vv) {
					cres = POW_IDX[i][l] * s + j;
					break;
				}
				vv = preMul(vv, cgen);
			}
			if (cres < 0) {
				throw new AssertionError();
			}
			BigInteger bp = BigInteger.valueOf(p);
			BigInteger md = bMod.divide(bp);
			res = res.add(md.modInverse(bp).multiply(md).multiply(BigInteger.valueOf(cres)));
		}
		return res.mod(bMod);
	}

	static void solve() throws Exception {
		int tests = scanInt();
//		int tests = 100;
//		Random rng = new Random(42);
		for (int test = 0; test < tests; test++) {
			long a = new BigInteger(scanString()).longValue(),
			     b = new BigInteger(scanString()).longValue();
//			long a = test * 12345678901L + 12345678901234567L, b = pow(a, 1999);
//			long a = rng.nextLong(), b = rng.nextLong();
			BigInteger logA = dlog(a), logB = dlog(b);
			BigInteger x;
			if (logB.signum() == 0) {
				x = BigInteger.ZERO;
			} else {
				BigInteger gcd = logA.gcd(logB).gcd(bMod);
				logA = logA.divide(gcd);
				logB = logB.divide(gcd);
				BigInteger curMod = bMod.divide(gcd);
				if (logA.gcd(curMod).compareTo(BigInteger.ONE) != 0) {
					x = BigInteger.ONE.negate();
				} else {
					x = logA.modInverse(curMod).multiply(logB).mod(curMod);
				}
			}
//			if (x.signum() >= 0 && pow(a, x.longValue()) != b) {
//				throw new AssertionError();
//			}
			out.println(x);
		}
	}

	static int scanInt() throws IOException {
		return parseInt(scanString());
	}

	static long scanLong() throws IOException {
		return parseLong(scanString());
	}

	static String scanString() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.System.exit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.StringTokenizer;

public class F {

	static void sortBy(int a[], int n, long v[]) {
		if (n == 0) {
			return;
		}
		for (int i = 1; i < n; i++) {
			int j = i;
			int ca = a[i];
			long cv = v[ca];
			do {
				int nj = (j - 1) >> 1;
				int na = a[nj];
				if (cv <= v[na]) {
					break;
				}
				a[j] = na;
				j = nj;
			} while (j != 0);
			a[j] = ca;
		}
		int ca = a[0];
		for (int i = n - 1; i > 0; i--) {
			int j = 0;
			while ((j << 1) + 2 + Integer.MIN_VALUE < i + Integer.MIN_VALUE) {
				j <<= 1;
				j += (v[a[j + 2]] > v[a[j + 1]]) ? 2 : 1;
			}
			if ((j << 1) + 2 == i) {
				j = (j << 1) + 1;
			}
			int na = a[i];
			a[i] = ca;
			ca = na;
			long cv = v[ca];
			while (j != 0 && v[a[j]] < cv) {
				j = (j - 1) >> 1;
			}
			while (j != 0) {
				na = a[j];
				a[j] = ca;
				ca = na;
				j = (j - 1) >> 1;
			}
		}
		a[0] = ca;
	}

	static final long MUL_BIT_TABLE[] = new long[64 * 64];
	static long mulBits(int i, int j) {
		int key = i * 64 + j;
		long res = MUL_BIT_TABLE[key];
		if (res == 0) {
			res = 1;
			for (int k = 5; k >= 0; k--) {
				if (((i ^ j) & (1 << k)) != 0) {
					res <<= 1 << k;
				}
			}
			for (int k = 5; k >= 0; k--) {
				if ((i & j & (1 << k)) != 0) {
					res = mul(res, 3L << ((1 << k) - 1));
				}
			}
			MUL_BIT_TABLE[key] = res;
		}
		return res;
	}

	static long mulSlow(long a, long b) {
		long res = 0;
		for (int i = 0; i < 64; i++) {
			if ((a & (1L << i)) == 0) {
				continue;
			}
			for (int j = 0; j < 64; j++) {
				if ((b & (1L << j)) == 0) {
					continue;
				}
				res ^= mulBits(i, j);
			}
		}
		return res;
	}

	static final long MUL_TABLE[] = new long[8 * 8 * 256 * 256];
	static long mul(long a, long b) {
		long res = 0;
		for (int i = 0; i < 8; i++) {
			int vi = (int) ((a >> (8 * i)) & 255);
			if (vi == 0) {
				continue;
			}
			for (int j = 0; j < 8; j++) {
				int vj = (int) ((b >> (8 * j)) & 255);
				if (vj == 0) {
					continue;
				}
				int key = ((i * 8 + j) * 256 + vi) * 256 + vj;
				long cres = MUL_TABLE[key];
				if (cres == 0) {
					cres = mulSlow((long) vi << (8 * i), (long) vj << (8 * j));
					MUL_TABLE[key] = cres;
				}
				res ^= cres;
			}
		}
		return res;
	}

	static long pow(long a, long e) {
		if (e == 0) {
			return 1;
		}
		long r = a;
		for (int i = 62 - Long.numberOfLeadingZeros(e); i >= 0; i--) {
			r = mul(r, r);
			if ((e & (1L << i)) != 0) {
				r = mul(r, a);
			}
		}
		return r;
	}

	static final long GEN = -Long.MAX_VALUE;
	static final int PRIMES[] = {3, 5, 17, 257, 641, 65537, 6700417};
	static final int PRIME_STEP[] = {1, 1, 1, 1, 1, 10, 1000};
	static final long POW_VALS[][] = new long[PRIMES.length][];
	static final int POW_IDX[][] = new int[PRIMES.length][];
	static {
		for (int i = 0; i < PRIMES.length; i++) {
			int p = PRIMES[i];
			int s = PRIME_STEP[i];
			int l = p / s;
			POW_VALS[i] = new long[l];
			POW_IDX[i] = new int[l];
			POW_VALS[i][0] = 1;
			long cgen = pow(GEN, Long.divideUnsigned(-1, p) * s);
			for (int j = 1; j < l; j++) {
				POW_VALS[i][j] = mul(POW_VALS[i][j - 1], cgen);
				POW_IDX[i][j] = j;
			}
			sortBy(POW_IDX[i], l, POW_VALS[i]);
		}
	}

	static final BigInteger bMod = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE);

	static BigInteger dlog(long v) {
		BigInteger res = BigInteger.ZERO;
		for (int i = 0; i < PRIMES.length; i++) {
			int p = PRIMES[i];
			int s = PRIME_STEP[i];
			int len = p / s;
			long vv = pow(v, Long.divideUnsigned(-1, p));
			long cgen = pow(GEN, -1 - Long.divideUnsigned(-1, p));
			int cres = -1;
			for (int j = 0; j < s; j++) {
				int l = 0, r = len;
				while (l < r) {
					int mid = (l + r) >> 1;
					if (POW_VALS[i][POW_IDX[i][mid]] < vv) {
						l = mid + 1;
					} else {
						r = mid;
					}
				}
				if (POW_VALS[i][POW_IDX[i][l]] == vv) {
					cres = POW_IDX[i][l] * s + j;
					break;
				}
				vv = mul(vv, cgen);
			}
			BigInteger bp = BigInteger.valueOf(p);
			BigInteger md = bMod.divide(bp);
			res = res.add(md.modInverse(bp).multiply(md).multiply(BigInteger.valueOf(cres)));
		}
		return res.mod(bMod);
	}

	static void solve() throws Exception {
		int tests = scanInt();
//		int tests = 100;
		for (int test = 0; test < tests; test++) {
			long a = new BigInteger(scanString()).longValue(),
			     b = new BigInteger(scanString()).longValue();
//			long a = 1, b = 1;
			BigInteger logA = dlog(a), logB = dlog(b);
			BigInteger x;
			if (logB.signum() == 0) {
				x = BigInteger.ZERO;
			} else {
				BigInteger gcd = logA.gcd(logB).gcd(bMod);
				logA = logA.divide(gcd);
				logB = logB.divide(gcd);
				BigInteger curMod = bMod.divide(gcd);
				if (logA.gcd(curMod).compareTo(BigInteger.ONE) != 0) {
					x = BigInteger.ONE.negate();
				} else {
					x = logA.modInverse(curMod).multiply(logB).mod(curMod);
				}
			}
			out.println(x);
		}
	}

	static int scanInt() throws IOException {
		return parseInt(scanString());
	}

	static long scanLong() throws IOException {
		return parseLong(scanString());
	}

	static String scanString() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}


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

public class Main {
	public static void main(String[] args) {
		InputReader in = new InputReader (System.in);
		PrintWriter out = new PrintWriter (System.out);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
	int[][] ans;
	int tot;
	class Line {
		int a,b,c,id;
	};

	public void solve (int TestNumber, InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int k = in.nextInt();
		Line[] road = new Line[n];
		for (int i = 0; i < n; ++i) {
			road[i] = new Line();//initialize is necessary
			road[i].a = in.nextInt();
			road[i].b = in.nextInt();
			road[i].c = in.nextInt();
			road[i].id = i+1;
		}
		ans = new int[k][2];
		tot = -1;
		calc(road, k);
		if (tot == -1) {
			out.println("NO");
			return;
		}
		out.println("YES");
		out.println(k-tot);
		for (int i = tot; i < k; ++i) {
			out.println(ans[i][0] + " " + ans[i][1]);
		}
	}
	//Java 特点，有了.length,就不用记录数组长度了；有了for each: 就不用枚举下标了
	private void calc(Line[] road, int k) {
		if (road.length > k*k) {
			if (k == 0) return;
			double pr = 1.0 - getPr(road.length,k);
			int cnt = 1;
			double s = pr;
			while (s > 1e-10) {
				++cnt;
				s *= pr;
			}
			Random rand = new Random(19950315L + System.currentTimeMillis());
			for (;cnt >= 0; --cnt) {
				Line p = road[rand.nextInt(road.length)];
				Line q = road[rand.nextInt(road.length)];
				int denom = p.a*q.b-p.b*q.a;
				if (denom == 0) continue;
				int x = -(p.c*q.b-p.b*q.c);
				int y = -(p.a*q.c-p.c*q.a);

				int num = 0;
				for (Line r : road) {
					if (r.a*x+r.b*y+r.c*denom == 0) ++num;
				}
				if (num>k) {
					ans[k-1][0] = p.id;
					ans[k-1][1] = q.id;
					int t_tot = 0;
					Line[] n_road = new Line[road.length - num];
					for (Line r : road) {
						if (r.a*x+r.b*y+r.c*denom != 0) {
							n_road[t_tot++] = r;
						}
					}
					calc(n_road, k-1);
					return;
				}
			}
		}
		else if (road.length == 0) {
			tot = k;
			return;
		}
		else {
			Random rand = new Random(19950315L + System.currentTimeMillis());
			Line p = road[rand.nextInt(road.length)];
			boolean any = false;
			for (Line q : road) {
				int denom = p.a*q.b-p.b*q.a;
				if (denom == 0) continue;
				any = true;
				int x = -(p.c*q.b-p.b*q.c);
				int y = -(p.a*q.c-p.c*q.a);

				int num = 0;
				for (Line r : road) {
					if (r.a*x+r.b*y+r.c*denom == 0) ++num;
				}
				Line[] n_road = new Line[road.length - num];
				ans[k-1][0] = p.id;
				ans[k-1][1] = q.id;
				int n_tot = 0;
				for (Line r : road) {
					if (r.a*x+r.b*y+r.c*denom != 0) {
						n_road[n_tot++] = r;
					}
				}
				calc(n_road, k-1);
				if (tot > -1) return;
			}
			if (!any) {
				ans[k-1][0] = p.id;
				ans[k-1][1] = -1;
				Line[] n_road = new Line[road.length - 1];
				int n_tot = 0;
				for (Line r : road) {
					n_road[n_tot++] = r;
				}
				calc(n_road, k-1);
			}
		}
	}

	private double getPr(int n, int k) {
		long ret = Long.MAX_VALUE;
		for (int small = 0; small < k; ++small) {
			int rem = n - small * k;
			int big = k - small;
			long pair = 0;
			for (int id = 0; id < big; ++id) {
				int size = rem / big;
				if (rem % big > id) ++size;
				pair += size*(size-1);
			}
			ret = Math.min(ret, pair);
		}
		return (double)ret/n/n;
	}
}

class InputReader {
	BufferedReader reader;
	StringTokenizer tokenizer;

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

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

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


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

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

    static class TaskD {
        int[] resu;
        int[] resv;
        int resunused;
        Random random;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            random = new Random(543715351L + System.currentTimeMillis());
            int n = in.nextInt();
            int k = in.nextInt();
            TaskD.Line[] roads = new TaskD.Line[n];
            for (int i = 0; i < n; ++i) {
                roads[i] = new TaskD.Line();
                roads[i].index = i + 1;
                roads[i].a = in.nextInt();
                roads[i].b = in.nextInt();
                roads[i].c = in.nextInt();
            }
            resu = new int[k];
            resv = new int[k];
            resunused = -1;
            doit(roads, k);
            if (resunused < 0) {
                out.println("NO");
            } else {
                out.println("YES");
                out.println(k - resunused);
                for (int i = resunused; i < k; ++i) {
                    out.println(resu[i] + " " + resv[i]);
                }
            }
        }

        private void doit(TaskD.Line[] roads, int k) {
            if (roads.length > k * k) {
                double pr = 1.0 - getPr(roads.length, k);
                int cnt = 0;
                double prod = 1;
                while (prod > 1e-10) {
                    prod *= pr;
                    ++cnt;
                }
                for (int step = 0; step < cnt; ++step) {
                    TaskD.Line p = roads[random.nextInt(roads.length)];
                    TaskD.Line q = roads[random.nextInt(roads.length)];
                    long denom = p.a * q.b - p.b * q.a;
                    if (denom == 0) continue;
                    long xnom = -(p.c * q.b - p.b * q.c);
                    long ynom = -(p.a * q.c - p.c * q.a);
                    int amt = 0;
                    for (TaskD.Line r : roads) {
                        if (r.a * xnom + r.b * ynom + r.c * denom == 0) {
                            ++amt;
                        }
                    }
                    if (amt > k) {
                        resu[k - 1] = p.index;
                        resv[k - 1] = q.index;
                        TaskD.Line[] remains = new TaskD.Line[roads.length - amt];
                        int ptr = 0;
                        for (TaskD.Line r : roads) {
                            if (r.a * xnom + r.b * ynom + r.c * denom != 0) {
                                remains[ptr++] = r;
                            }
                        }
                        doit(remains, k - 1);
                        return;
                    }
                }
            } else if (roads.length == 0) {
                resunused = k;
            } else {
                TaskD.Line p = roads[random.nextInt(roads.length)];
                boolean any = false;
                boolean[] mark = new boolean[roads.length];
                for (int qi = 0; qi < roads.length; ++qi)
                    if (!mark[qi]) {
                        TaskD.Line q = roads[qi];
                        long denom = p.a * q.b - p.b * q.a;
                        if (denom == 0) continue;
                        long xnom = -(p.c * q.b - p.b * q.c);
                        long ynom = -(p.a * q.c - p.c * q.a);
                        any = true;
                        int amt = 0;
                        for (int i = 0; i < roads.length; ++i) {
                            TaskD.Line r = roads[i];
                            if (r.a * xnom + r.b * ynom + r.c * denom == 0) {
                                ++amt;
                                mark[i] = true;
                            }
                        }
                        resu[k - 1] = p.index;
                        resv[k - 1] = q.index;
                        TaskD.Line[] remains = new TaskD.Line[roads.length - amt];
                        int ptr = 0;
                        for (TaskD.Line r : roads) {
                            if (r.a * xnom + r.b * ynom + r.c * denom != 0) {
                                remains[ptr++] = r;
                            }
                        }
                        doit(remains, k - 1);
                        if (resunused >= 0) return;
                    }
                if (!any) {
                    resu[k - 1] = p.index;
                    resv[k - 1] = -1;
                    TaskD.Line[] remains = new TaskD.Line[roads.length - 1];
                    int ptr = 0;
                    for (TaskD.Line r : roads) {
                        if (r != p) {
                            remains[ptr++] = r;
                        }
                    }
                    doit(remains, k - 1);
                }
            }
        }

        private double getPr(int n, int k) {
            long minPairs = Long.MAX_VALUE;
            for (int numSmall = 0; numSmall < k; ++numSmall) {
                int remains = n - k * numSmall;
                int numBig = k - numSmall;
                long numPairs = 0;
                for (int i = 0; i < numBig; ++i) {
                    long size = remains / numBig;
                    if (i < remains % numBig) ++size;
                    numPairs += size * (size - 1);
                }
                minPairs = Math.min(minPairs, numPairs);
            }
            return minPairs / (double) n / n;
        }

        static class Line {
            long a;
            long b;
            long c;
            int index;

        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

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

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

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

    }
}


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

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

    static class TaskD {
        int[] resu;
        int[] resv;
        int resunused;
        Random random;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            random = new Random(543715351L + System.currentTimeMillis());
            int n = in.nextInt();
            int k = in.nextInt();
            TaskD.Line[] roads = new TaskD.Line[n];
            for (int i = 0; i < n; ++i) {
                roads[i] = new TaskD.Line();
                roads[i].index = i + 1;
                roads[i].a = in.nextInt();
                roads[i].b = in.nextInt();
                roads[i].c = in.nextInt();
            }
            resu = new int[k];
            resv = new int[k];
            resunused = -1;
            doit(roads, k);
            if (resunused < 0) {
                out.println("NO");
            } else {
                out.println("YES");
                out.println(k - resunused);
                for (int i = resunused; i < k; ++i) {
                    out.println(resu[i] + " " + resv[i]);
                }
            }
        }

        private void doit(TaskD.Line[] roads, int k) {
            if (roads.length > k * k) {
                if (k == 0) return;
                double pr = 1.0 - getPr(roads.length, k);
                int cnt = 0;
                double prod = 1;
                while (prod > 1e-10) {
                    prod *= pr;
                    ++cnt;
                }
                for (int step = 0; step < cnt; ++step) {
                    TaskD.Line p = roads[random.nextInt(roads.length)];
                    TaskD.Line q = roads[random.nextInt(roads.length)];
                    long denom = p.a * q.b - p.b * q.a;
                    if (denom == 0) continue;
                    long xnom = -(p.c * q.b - p.b * q.c);
                    long ynom = -(p.a * q.c - p.c * q.a);
                    int amt = 0;
                    for (TaskD.Line r : roads) {
                        if (r.a * xnom + r.b * ynom + r.c * denom == 0) {
                            ++amt;
                        }
                    }
                    if (amt > k) {
                        resu[k - 1] = p.index;
                        resv[k - 1] = q.index;
                        TaskD.Line[] remains = new TaskD.Line[roads.length - amt];
                        int ptr = 0;
                        for (TaskD.Line r : roads) {
                            if (r.a * xnom + r.b * ynom + r.c * denom != 0) {
                                remains[ptr++] = r;
                            }
                        }
                        doit(remains, k - 1);
                        return;
                    }
                }
            } else if (roads.length == 0) {
                resunused = k;
            } else {
                TaskD.Line p = roads[random.nextInt(roads.length)];
                boolean any = false;
                boolean[] mark = new boolean[roads.length];
                for (int qi = 0; qi < roads.length; ++qi)
                    if (!mark[qi]) {
                        TaskD.Line q = roads[qi];
                        long denom = p.a * q.b - p.b * q.a;
                        if (denom == 0) continue;
                        long xnom = -(p.c * q.b - p.b * q.c);
                        long ynom = -(p.a * q.c - p.c * q.a);
                        any = true;
                        int amt = 0;
                        for (int i = 0; i < roads.length; ++i) {
                            TaskD.Line r = roads[i];
                            if (r.a * xnom + r.b * ynom + r.c * denom == 0) {
                                ++amt;
                                mark[i] = true;
                            }
                        }
                        resu[k - 1] = p.index;
                        resv[k - 1] = q.index;
                        TaskD.Line[] remains = new TaskD.Line[roads.length - amt];
                        int ptr = 0;
                        for (TaskD.Line r : roads) {
                            if (r.a * xnom + r.b * ynom + r.c * denom != 0) {
                                remains[ptr++] = r;
                            }
                        }
                        doit(remains, k - 1);
                        if (resunused >= 0) return;
                    }
                if (!any) {
                    resu[k - 1] = p.index;
                    resv[k - 1] = -1;
                    TaskD.Line[] remains = new TaskD.Line[roads.length - 1];
                    int ptr = 0;
                    for (TaskD.Line r : roads) {
                        if (r != p) {
                            remains[ptr++] = r;
                        }
                    }
                    doit(remains, k - 1);
                }
            }
        }

        private double getPr(int n, int k) {
            long minPairs = Long.MAX_VALUE;
            for (int numSmall = 0; numSmall < k; ++numSmall) {
                int remains = n - k * numSmall;
                int numBig = k - numSmall;
                long numPairs = 0;
                for (int i = 0; i < numBig; ++i) {
                    long size = remains / numBig;
                    if (i < remains % numBig) ++size;
                    numPairs += size * (size - 1);
                }
                minPairs = Math.min(minPairs, numPairs);
            }
            return minPairs / (double) n / n;
        }

        static class Line {
            long a;
            long b;
            long c;
            int index;

        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

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

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

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

    }
}


import java.io.*;
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];

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


// 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 {
						long x0 = ma > 0 ? dq[ma - 1][mb][mc][0] * ma % MD : 0;
						long x1 = mb > 0 ? dq[ma][mb - 1][mc][1] * mb % MD : 0;
						long x2 = mc > 0 ? dq[ma][mb][mc - 1][2] * mc % MD : 0;
						dp[ma][mb][mc] = (int) ((x0 + x1 + x2) % MD);
						dq[ma][mb][mc][0] = (int) ((x1 + x2) % MD);
						dq[ma][mb][mc][1] = (int) ((x2 + x0) % MD);
						dq[ma][mb][mc][2] = (int) ((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,lg[];
	static int [][]memo;
	static int dp(int msk,int rem,int lastG) {
		if(rem==0)
			return 1;

		int ans=0;
		int currMsk=msk;
		while(currMsk>0) {
			int x=currMsk&-currMsk;
			int i=lg[x];
			currMsk-=x;
			if(rem>=t[i] && g[i]!=lastG)
				ans+=dp(msk&(~(1<<i)),rem-t[i],g[i]);
				if(ans>=MOD)
					ans-=MOD;
		}

		return ans;
	}
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner();
		PrintWriter out = new PrintWriter(System.out);
		n=sc.nextInt();
		int T=sc.nextInt();
		t=new int [n];
		g=new int [n];
		lg=new int [1<<n];
		for(int i=0;i<n;i++)
			lg[1<<i]=i;
		for(int i=0;i<n;i++) {
			t[i]=sc.nextInt();
			g[i]=sc.nextInt()-1;
		}

		out.println(dp((1<<n)-1, T, 3));
		out.close();

	}

	static class Scanner {
		BufferedReader br;
		StringTokenizer st;

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

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

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

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

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

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

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

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

	}

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.InputStreamReader;
import java.io.FileNotFoundException;
import java.util.TreeMap;
import java.util.StringTokenizer;
import java.util.Map;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;

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

    static class TaskD {
        public void solve(int testNumber, IOReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            int[] x = in.readIntArray(n);
            Arrays.sort(x);

            Food[] fs = new Food[m];
            for (int i = 0; i < m; i++) {
                fs[i] = new Food(in.nextInt(), in.nextInt());
            }
            Arrays.sort(fs);

            Event[] es = new Event[m * 2 + n];
            for (int i = 0; i < m; i++) {
                es[i] = new Event(fs[i].x - fs[i].time, Event.BEGIN, i);
                es[m + i] = new Event(fs[i].x + fs[i].time, Event.END, i);
            }
            for (int i = 0; i < n; i++) {
                es[m * 2 + i] = new Event(x[i], Event.DOG, i);
            }
            Arrays.sort(es);

            int ans = 0;
            TreeMap<Integer, Integer> cntEndOn = new TreeMap<>();
            TreeMap<Integer, Integer> inactive = new TreeMap<>();

            // .first -- unused
            // .second -- used
            for (int i = 0; i < es.length; i++) {
                Event cur = es[i];
                if (cur.type == Event.BEGIN) {

                    int end = fs[cur.idx].time + fs[cur.idx].x;
//                Pair<Integer, Integer> prev = cntEndOn.getOrDefault(end, new Pair<>(0, 0));
                    int prev = cntEndOn.getOrDefault(end, 0) + 1;
                    cntEndOn.put(end, prev);

                } else if (cur.type == Event.END) {

                    boolean over1 = false;
                    boolean over2 = false;
//                Pair<Integer, Integer> prev = cntEndOn.get(cur.x);
                    int prev_first = cntEndOn.getOrDefault(cur.x, 0);
                    int prev_second = inactive.getOrDefault(cur.x, 0);

                    if (prev_second > 0) {
                        prev_second--;
                    } else {
                        if (prev_first > 0) {
                            prev_first--;
                        }
                    }
                    if (prev_first == 0) {
                        over1 = true;
                    }
                    if (prev_second == 0) {
                        over2 = true;
                    }

                    if (!over1) {
                        cntEndOn.put(cur.x, prev_first);
                    } else {
                        cntEndOn.remove(cur.x);
                    }

                    if (!over2) {
                        inactive.put(cur.x, prev_second);
                    } else {
                        inactive.remove(cur.x);
                    }

                } else {

                    if (cntEndOn.size() > 0) {
                        int key = cntEndOn.firstKey();

//                    Pair<Integer, Integer> prev = cntEndOn.get(key);
                        int prev_first = cntEndOn.getOrDefault(key, 0);
                        int prev_second = inactive.getOrDefault(key, 0);
                        boolean over1 = false;
                        if (prev_first > 0) {
                            prev_first--;
                            prev_second++;
                            ans++;
                        }
                        if (prev_first == 0) {
                            over1 = true;
                        }

                        if (!over1) {
                            cntEndOn.put(key, prev_first);
                        } else {
                            cntEndOn.remove(key);
                        }
                        inactive.put(key, prev_second);
                    }

                }
            }
            out.println(ans);
        }

    }

    static class Event implements Comparable<Event> {
        int x;
        int type;
        int idx;
        static final int BEGIN = -1;
        static final int END = 1;
        static final int DOG = 0;

        public Event(int x, int type, int idx) {
            this.x = x;
            this.type = type;
            this.idx = idx;
        }

        public int compareTo(Event o) {
            if (x == o.x) {
                return Integer.compare(type, o.type);
            }
            return Integer.compare(x, o.x);
        }

    }

    static class Food implements Comparable<Food> {
        int x;
        int time;

        public Food(int x, int time) {
            this.x = x;
            this.time = time;
        }

        public int compareTo(Food o) {
            if (x == o.x) {
                return Integer.compare(time, o.time);
            }
            return Integer.compare(x, o.x);
        }

    }

    static class IOReader {
        private BufferedReader reader;
        private StringTokenizer tokenizer;

        public String nextToken() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (Exception e) {
                    return null;
                }
            }
            return tokenizer.nextToken();
        }

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

        public int[] readIntArray(int count) {
            int[] array = new int[count];
            for (int i = 0; i < count; i++) {
                array[i] = nextInt();
            }
            return array;
        }

        private IOReader(BufferedReader bufferedReader) {
            reader = bufferedReader;
        }

        public IOReader(String filename) {
            try {
                reader = new BufferedReader(new FileReader(filename));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public IOReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream));
        }

    }
}


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

public class Codeforces810E {
	public static int[] global = new int[100];

	public static void main(String[] args) throws IOException {
		global[0] = 1;
		for (int i = 1; i < 100; i++) {
			global[i] = (2*global[i-1])%1000000007;
		}
		int[] twopower = new int[100];
		twopower[0] = 1;
		for (int i = 1; i < 100; i++) {
			twopower[i] = (twopower[i-1]*2)%1000000007;
		}
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(System.out);
		String[] sp = br.readLine().split(" ");
		int q = Integer.parseInt(sp[0]);
		for (int i = 0; i < q; i++) {
			sp = br.readLine().split(" ");
			int x1 = Integer.parseInt(sp[0]);
			int y1 = Integer.parseInt(sp[1]);
			int x2 = Integer.parseInt(sp[2]);
			int y2 = Integer.parseInt(sp[3]);
			int k = Integer.parseInt(sp[4]);
			int answer = 0;
			if ((x1 == 1) && (y1 == 1)) {
				answer = answer(x2, y2, k);
			}
			else if (x1 == 1) {
				answer = answer(x2, y2, k)-answer(x2, y1-1, k);
			}
			else if (y1 == 1) {
				answer = answer(x2, y2, k) - answer(x1-1, y2, k);
			}
			else {
				answer = answer(x2, y2, k) - answer(x1-1, y2, k) - answer(x2, y1-1, k) + answer(x1-1, y1-1, k);
			}
			answer %= 1000000007;
			if (answer < 0)
				answer += 1000000007;
			pw.println(answer);
		}
		pw.close();
	}

	public static int answer(int m, int n, int k) {
		int tmp = m;
		int counter = 0;
		int counter2 = 0;
		while (tmp > 0) {
			if (tmp%2 == 1)
				counter++;
			counter2++;
			tmp = tmp/2;
		}
		int[][] mlist = new int[counter][2];
		counter--;
		for (int i = counter2-1; i >= 0; i--) {
			if ((m >> i)%2 == 1) {
				mlist[counter][0] = (m >> i)-1;
				mlist[counter][1] = i;
				counter--;
			}
		}

		tmp = n;
		counter = 0;
		counter2 = 0;
		while (tmp > 0) {
			if (tmp%2 == 1)
				counter++;
			counter2++;
			tmp = tmp/2;
		}
		int[][] nlist = new int[counter][2];
		counter--;
		for (int i = counter2-1; i >= 0; i--) {
			if ((n >> i)%2 == 1) {
				nlist[counter][0] = (n >> i)-1;
				nlist[counter][1] = i;
				counter--;
			}
		}

		int answer = 0;

		for (int i = 0; i < mlist.length; i++) {
			for (int j = 0; j < nlist.length; j++) {
				answer = (answer + sum(mlist[i][1], nlist[j][1], mlist[i][0], nlist[j][0], k))%1000000007;
			}
		}

		return answer;
	}

	public static int sum(int m, int n, int r, int s, int k) {
		if (m < n) {
			int temp = m;
			m = n;
			n = temp;
			temp = r;
			r = s;
			s = temp;
		}
		int t = s >> (m-n);
		int u = r^t;
		long val = 0;
		if (k > u*global[m]) {
			int min = u*global[m];
			int max = Math.min(k, (u+1)*global[m]);
			val = (((long) max)*((long) max+1))/2 - (((long) min)*((long)min+1))/2;
		}
		val %= 1000000007;
		val *= global[n];
		val %= 1000000007;
		return (int) val;
	}

}


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

public class Main {

	private static final String NO = "NO";
	private static final String YES = "YES";
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	private static final long MOD = 1000000007;

	void solve() {
		int T = 1;
		for (int i = 0; i < T; i++)
			solve(i);
	}

	long p[];

	void solve(int T) {
		int n = ni();
		p = new long[64];
		p[0] = 1;
		for (int i = 1; i < 60; i++)
			p[i] = p[i - 1] * 2;

		for (int i = 0; i < n; i++) {
			int a[] = na(5);
			long ans = work(a[2], a[3], a[4], 0) - work(a[0] - 1, a[3], a[4], 0) - work(a[2], a[1] - 1, a[4], 0)
					+ work(a[0] - 1, a[1] - 1, a[4], 0);
			ans %= MOD;
			out.println((ans + MOD) % MOD);
		}
	}

	long work(long x, long y, long k, long lazy) {
		if (x <= 0 || y <= 0)
			return 0;
		if (k <= 0)
			return 0;
		if (x > y) {
			long tmp = x;
			x = y;
			y = tmp;
		}
		int t = 0;
		while (p[t] <= y)
			t++;

		long ans;
		if (y == p[t - 1]) {
			long tmpa, tmpb;
			if (p[t - 1] < k)// all numbers is within [1..k], count them all
			{
				tmpa = p[t - 1];
				tmpa = tmpa * (tmpa + 1) / 2;
				tmpa %= MOD;
				tmpa *= x;
				tmpa %= MOD;
				tmpb = (lazy * y) % MOD;
				tmpb *= x;
				tmpb %= MOD;
				ans = (tmpa + tmpb) % MOD;
			} else// p[t-1]>=k only less or equal to k is needed
			{
				tmpa = k;
				tmpa = tmpa * (tmpa + 1) / 2;
				tmpa %= MOD;
				tmpa *= x;
				tmpa %= MOD;
				tmpb = (lazy * k) % MOD;
				tmpb *= x;
				tmpb %= MOD;
				ans = (tmpa + tmpb) % MOD;
			}
		} else// y > p[t-1]
		{
			if (x < p[t - 1]) {
				ans = work(x, p[t - 1], k, lazy);
				ans = (ans + work(x, y - p[t - 1], k - p[t - 1], lazy + p[t - 1])) % MOD;
			} else {
				ans = work(p[t - 1], p[t - 1], k, lazy);
				ans = (ans + work(x - p[t - 1], p[t - 1], k - p[t - 1], lazy + p[t - 1])) % MOD;
				ans = (ans + work(p[t - 1], y - p[t - 1], k - p[t - 1], lazy + p[t - 1])) % MOD;
				ans = (ans + work(x - p[t - 1], y - p[t - 1], k, lazy)) % MOD;
			}
		}
//		tr(x, y, k, lazy, ans);

		return ans;
	}

	// a^b
	long power(long a, long b) {
		long x = 1, y = a;
		while (b > 0) {
			if (b % 2 != 0) {
				x = (x * y) % MOD;
			}
			y = (y * y) % MOD;
			b /= 2;
		}
		return x % MOD;
	}

	private long gcd(long a, long b) {
		while (a != 0) {
			long tmp = b % a;
			b = a;
			a = tmp;
		}
		return b;
	}

	void run() throws Exception {
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

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

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

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

	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) {
			if (!(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 List<Integer> na2(int n) {
		List<Integer> a = new ArrayList<Integer>();
		for (int i = 0; i < n; i++)
			a.add(ni());
		return a;
	}

	private int[][] na(int n, int m) {
		int[][] a = new int[n][];
		for (int i = 0; i < n; i++)
			a[i] = na(m);
		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(int n) {
		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nl();
		return a;
	}

	private long[][] nl(int n, int m) {
		long[][] a = new long[n][];
		for (int i = 0; i < n; i++)
			a[i] = nl(m);
		return a;
	}

	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 static void tr(Object... o) {
		System.out.println(Arrays.deepToString(o));
	}

	public class Pair<K, V> {

		/**
		 * Key of this Pair.
		 */
		private K key;

		/**
		 * Gets the key for this pair.
		 *
		 * @return key for this pair
		 */
		public K getKey() {
			return key;
		}

		/**
		 * Value of this this Pair.
		 */
		private V value;

		/**
		 * Gets the value for this pair.
		 *
		 * @return value for this pair
		 */
		public V getValue() {
			return value;
		}

		/**
		 * Creates a new pair
		 *
		 * @param key   The key for this pair
		 * @param value The value to use for this pair
		 */
		public Pair(K key, V value) {
			this.key = key;
			this.value = value;
		}

		/**
		 *

		 * String representation of this Pair.
		 *

		 *
		 *

		 * The default name/value delimiter '=' is always used.
		 *

		 *
		 * @return String representation of this Pair
		 */
		@Override
		public String toString() {
			return key + "=" + value;
		}

		/**
		 *

		 * Generate a hash code for this Pair.
		 *

		 *
		 *

		 * The hash code is calculated using both the name and the value of the
		 * Pair.
		 *

		 *
		 * @return hash code for this Pair
		 */
		@Override
		public int hashCode() {
			// name's hashCode is multiplied by an arbitrary prime number (13)
			// in order to make sure there is a difference in the hashCode between
			// these two parameters:
			// name: a value: aa
			// name: aa value: a
			return key.hashCode() * 13 + (value == null ? 0 : value.hashCode());
		}

		/**
		 *

		 * Test this Pair for equality with another Object.
		 *

		 *
		 *

		 * If the Object to be tested is not a Pair or is
		 * null, then this method returns false.
		 *

		 *
		 *

		 * Two Pairs are considered equal if and only if both the names and
		 * values are equal.
		 *

		 *
		 * @param o the Object to test for equality with this
		 *          Pair
		 * @return true if the given Object is equal to this
		 *         Pair else false
		 */
		@Override
		public boolean equals(Object o) {
			if (this == o)
				return true;
			if (o instanceof Pair) {
				Pair pair = (Pair) o;
				if (key != null ? !key.equals(pair.key) : pair.key != null)
					return false;
				if (value != null ? !value.equals(pair.value) : pair.value != null)
					return false;
				return true;
			}
			return false;
		}
	}

}


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

/**
 * @author Don Li
 */
public class FindACar {

    int N = 30;
    int MOD = (int) 1e9 + 7;

    int a, b, c;

    int[][][][] dp = new int[N + 1][2][2][2];
    int[][][][] cnt = new int[N + 1][2][2][2];

    void solve() {
        int q = in.nextInt();
        while (q-- > 0) {
            int x1 = in.nextInt() - 1, y1 = in.nextInt() - 1, x2 = in.nextInt() - 1, y2 = in.nextInt() - 1, k = in.nextInt() - 1;

            long ans = 0;
            ans = (ans + calc(x2, y2, k)) % MOD;
            ans = (ans - calc(x1 - 1, y2, k) + MOD) % MOD;
            ans = (ans - calc(x2, y1 - 1, k) + MOD) % MOD;
            ans = (ans + calc(x1 - 1, y1 - 1, k)) % MOD;

            out.println(ans);
        }
    }

    int calc(int x, int y, int k) {
        if (x < 0 || y < 0) return 0;

        for (int i = 0; i <= N; i++)
            for (int j = 0; j < 2; j++)
                for (int u = 0; u < 2; u++)
                    for (int v = 0; v < 2; v++)
                        dp[i][j][u][v] = cnt[i][j][u][v] = -1;

        a = x;
        b = y;
        c = k;
        return dfs1(N, 1, 1, 1);
    }

    int dfs1(int i, int ea, int eb, int ec) {
        if (i < 0) return 1;
        if (dp[i][ea][eb][ec] >= 0) return dp[i][ea][eb][ec];

        int bit_a = (a >> i) & 1;
        int bit_b = (b >> i) & 1;
        int bit_c = (c >> i) & 1;

        long res = 0;

        int nec = ec == 1 && bit_c == 0 ? 1 : 0;
        int nea = ea == 1 && bit_a == 0 ? 1 : 0;
        int neb = eb == 1 && bit_b == 0 ? 1 : 0;
        res = (res + dfs1(i - 1, nea, neb, nec)) % MOD;

        if ((eb == 0 || bit_b == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 0 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + (1L << i) * dfs2(i - 1, nea, neb, nec) % MOD + dfs1(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 0 ? 1 : 0;
            res = (res + (1L << i) * dfs2(i - 1, nea, neb, nec) % MOD + dfs1(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (eb == 0 || bit_b == 1)) {
            nec = ec == 1 && bit_c == 0 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + dfs1(i - 1, nea, neb, nec)) % MOD;
        }

        return dp[i][ea][eb][ec] = (int) res;
    }

    int dfs2(int i, int ea, int eb, int ec) {
        if (i < 0) return 1;
        if (cnt[i][ea][eb][ec] >= 0) return cnt[i][ea][eb][ec];

        int bit_a = (a >> i) & 1;
        int bit_b = (b >> i) & 1;
        int bit_c = (c >> i) & 1;

        long res = 0;

        int nec = ec == 1 && bit_c == 0 ? 1 : 0;
        int nea = ea == 1 && bit_a == 0 ? 1 : 0;
        int neb = eb == 1 && bit_b == 0 ? 1 : 0;
        res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;

        if ((eb == 0 || bit_b == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 0 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 0 ? 1 : 0;
            res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (eb == 0 || bit_b == 1)) {
            nec = ec == 1 && bit_c == 0 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;
        }

        return cnt[i][ea][eb][ec] = (int) res;
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new FindACar().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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


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

/**
 * @author Don Li
 */
public class FindACar {

    int N = 30;
    int MOD = (int) 1e9 + 7;

    int a, b, c;

    int[][][][] dp = new int[N + 1][2][2][2];
    int[][][][] cnt = new int[N + 1][2][2][2];

    void solve() {
        int q = in.nextInt();
        while (q-- > 0) {
            int x1 = in.nextInt() - 1, y1 = in.nextInt() - 1, x2 = in.nextInt() - 1, y2 = in.nextInt() - 1, k = in.nextInt() - 1;

            long ans = 0;
            ans = (ans + calc(x2, y2, k)) % MOD;
            ans = (ans - calc(x1 - 1, y2, k) + MOD) % MOD;
            ans = (ans - calc(x2, y1 - 1, k) + MOD) % MOD;
            ans = (ans + calc(x1 - 1, y1 - 1, k)) % MOD;

            out.println(ans);
        }
    }

    int calc(int x, int y, int k) {
        if (x < 0 || y < 0) return 0;

        for (int i = 0; i <= N; i++)
            for (int j = 0; j < 2; j++)
                for (int u = 0; u < 2; u++)
                    for (int v = 0; v < 2; v++)
                        dp[i][j][u][v] = cnt[i][j][u][v] = -1;

        a = x;
        b = y;
        c = k;
        return dfs1(N, 1, 1, 1);
    }

    int dfs1(int i, int ea, int eb, int ec) {
        if (i < 0) return 1;
        if (dp[i][ea][eb][ec] >= 0) return dp[i][ea][eb][ec];

        int bit_a = (a >> i) & 1;
        int bit_b = (b >> i) & 1;
        int bit_c = (c >> i) & 1;

        long res = 0;

        int nec = ec == 1 && bit_c == 0 ? 1 : 0;
        int nea = ea == 1 && bit_a == 0 ? 1 : 0;
        int neb = eb == 1 && bit_b == 0 ? 1 : 0;
        res = (res + dfs1(i - 1, nea, neb, nec)) % MOD;

        if ((eb == 0 || bit_b == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 0 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + (1L << i) * dfs2(i - 1, nea, neb, nec) % MOD + dfs1(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 0 ? 1 : 0;
            res = (res + (1L << i) * dfs2(i - 1, nea, neb, nec) % MOD + dfs1(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (eb == 0 || bit_b == 1)) {
            nec = ec == 1 && bit_c == 0 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + dfs1(i - 1, nea, neb, nec)) % MOD;
        }

        return (int) res;
    }

    int dfs2(int i, int ea, int eb, int ec) {
        if (i < 0) return 1;
        if (cnt[i][ea][eb][ec] >= 0) return cnt[i][ea][eb][ec];

        int bit_a = (a >> i) & 1;
        int bit_b = (b >> i) & 1;
        int bit_c = (c >> i) & 1;

        long res = 0;

        int nec = ec == 1 && bit_c == 0 ? 1 : 0;
        int nea = ea == 1 && bit_a == 0 ? 1 : 0;
        int neb = eb == 1 && bit_b == 0 ? 1 : 0;
        res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;

        if ((eb == 0 || bit_b == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 0 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (ec == 0 || bit_c == 1)) {
            nec = ec == 1 && bit_c == 1 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 0 ? 1 : 0;
            res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;
        }

        if ((ea == 0 || bit_a == 1) && (eb == 0 || bit_b == 1)) {
            nec = ec == 1 && bit_c == 0 ? 1 : 0;
            nea = ea == 1 && bit_a == 1 ? 1 : 0;
            neb = eb == 1 && bit_b == 1 ? 1 : 0;
            res = (res + dfs2(i - 1, nea, neb, nec)) % MOD;
        }

        return (int) res;
    }

    public static void main(String[] args) {
        in = new FastScanner(new BufferedReader(new InputStreamReader(System.in)));
        out = new PrintWriter(System.out);
        new FindACar().solve();
        out.close();
    }

    static FastScanner in;
    static PrintWriter out;

    static class FastScanner {
        BufferedReader in;
        StringTokenizer st;

        public FastScanner(BufferedReader in) {
            this.in = in;
        }

        public String nextToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

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

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

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


import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.function.Consumer;

public class Solution456 {

    static MyScanner sc;
    private static PrintWriter out;
    static long M2 = 1_000_000_000L + 7;

    public static void main(String[] s) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();

//
//        stringBuilder.append("50 4950 ");
//        for (int t = 0; t < 50; t++) {
//            stringBuilder.append(" 99 100 80  ");
//        }

//        stringBuilder.append("4 319\n" +
//                "63 79 89\n" +
//                "79 97 91\n" +
//                "75 87 88\n" +
//                "75 90 83");

        if (stringBuilder.length() == 0) {
            sc = new MyScanner(System.in);
        } else {
            sc = new MyScanner(new BufferedReader(new StringReader(stringBuilder.toString())));
        }

        out = new PrintWriter(new OutputStreamWriter(System.out));

        initData();
        solve();
        out.flush();
    }

    private static void initData() {
    }

    private static void solve() throws IOException {
        int n = sc.nextInt();
        tx = sc.nextInt();
        int[][] data = new int[n][];
        for (int i = 0; i < n; i++) {
            data[i] = sc.na(3);
        }
        double max = 1000000000;
        double min = 0;

        while (!r(max, min)) {
            double mid = (max + min) / 2;
            if (v(data, mid)) {
                max = mid;
            } else {
                min = mid;
            }
        }
        out.println(min);
    }

    static boolean r(double l1, double l2) {

        return Math.abs(l1 - l2) / Math.max(1, Math.max(l1, l2)) < 0.0000000000001;
    }

    private static boolean v(int[][] data, double mid) {
        val = mid;
        return sv(data);
    }

    private static double val;
    private static int tx;

    private static boolean sv(int[][] data) {
        double[][] switchr = new double[data.length + 1][tx + 1];

        for (int k = data.length - 1; k >= 0; k--) {
            for (int t = 0; t <= tx; t++) {
                int p1 = data[k][0];
                int p2 = data[k][1];
                int v = data[k][2];
                int v1 = t + p1;
                int v2 = t + p2;
                double t1 = (v1 > tx) ? (p1 + val) : (p1 + switchr[k + 1][v1]);
                double t2 = (v2 > tx) ? (p2 + val) : (p2 + switchr[k + 1][v2]);
                double exp = (t1 * v + (100 - v) * t2) / 100;
                switchr[k][t] = Math.min(exp, val);
            }
        }

        return !r(switchr[0][0], val);
    }

    private static final class LogTreePar {

        private final int[] levels;
        private final int[][] parents;

        public LogTreePar(int n) {
            levels = new int[n];
            parents = new int[n][19];
            Arrays.fill(levels, -1);
            for (int[] x : parents) {
                Arrays.fill(x, -1);
            }
        }

        public boolean ispar(int f, int l) {
            if (levels[f] >= levels[l]) return false;
            int diff = levels[l] - levels[f];
            return up(l, diff) == f;
        }

        private int up(int item, int diff) {
            int r = 0;
            while (diff > 0 && item >= 0) {
                if (isset(diff, r)) {
                    diff ^= 1 << r;
                    item = parents[item][r];
                }
                r++;
            }
            return item;
        }

        public void add(int item, int parent) {
            parents[item][0] = parent;
            clt(item);
        }

        protected void clt(int item) {
            levels[item] = levels[parents[item][0]] + 1;
            for (int l = 1; l < 19; l++) {
                if (parents[item][l - 1] == -1) break;
                parents[item][l] = parents[parents[item][l - 1]][l - 1];
            }
        }

        public int lca(int f, int l) {
            if (levels[f] > levels[l]) {
                return lca(l, f);
            }
            return lca1(f, up(l, levels[l] - levels[f]));
        }

        private int lca1(int f1, int f2) {
            for (int r = 18; r >= 0 && f1 != f2; r--) {
                if (parents[f1][r] != parents[f2][r]) {
                    f1 = parents[f1][r];
                    f2 = parents[f2][r];
                }
            }
            return f1 == f2 ? f1 : parents[f1][0];
        }
    }

    private static class P {
        private boolean b;
        private final int ind;
        private final int parent;

        public P(int i, boolean b, int par) {
            this.ind = i;
            this.b = b;
            this.parent = par;

        }
    }

    private static void dfs(int start, int[][] neig, Consumer<int[]> onAdd, Consumer<int[]> onRemove) {
        ArrayList<P> toVisit = new ArrayList<P>(3000);
        toVisit.add(new P(start, true, -1));
        boolean[] vis = new boolean[neig.length];
        vis[start] = true;
        int[] level = new int[neig.length];
        while (toVisit.size() > 0) {
            P ppr = toVisit.remove(toVisit.size() - 1);
            if (!ppr.b) {
                onRemove.accept(new int[]{ppr.ind, level[ppr.ind], ppr.parent});
                continue;
            }
            ppr.b = false;
            int i = ppr.ind;
            toVisit.add(ppr);
            onAdd.accept(new int[]{ppr.ind, level[ppr.ind], ppr.parent});
            for (int kk : neig[i]) {
                if (!vis[kk]) {
                    vis[kk] = true;
                    level[kk] = level[i] + 1;
                    toVisit.add(new P(kk, true, i));
                }
            }
        }

    }

    private static int[][] tr(int n) {
        int[][] x = new int[2][n - 1];
        for (int i = 0; i < n - 1; i++) {
            x[0][i] = sc.nextInt() - 1;
            x[1][i] = sc.nextInt() - 1;
        }
        return pn(x, n);
    }

    private static int[][] pn(int[][] x, int n) {
        int[] ct = new int[n];
        int[][] res = new int[n][];
        for (int v : x[0]) {
            ct[v]++;
        }
        for (int v : x[1]) {
            ct[v]++;
        }
        for (int l = 0; l < n; l++) {
            res[l] = new int[ct[l]];
        }
        for (int i = 0; i < x[0].length; i++) {
            res[x[0][i]][--ct[x[0][i]]] = x[1][i];
            res[x[1][i]][--ct[x[1][i]]] = x[0][i];
        }
        return res;
    }

    private static boolean isset(long i, int k) {
        return (i & (1 << k)) > 0;
    }

    private static void solveT() throws IOException {
        int t = sc.nextInt();
        while (t-- > 0) {
            solve();
        }
    }

    private static long gcd(long l, long l1) {
        if (l > l1) return gcd(l1, l);
        if (l == 0) return l1;
        return gcd(l1 % l, l);
    }

    private static long pow(long a, long b, long m) {
        if (b == 0) return 1;
        if (b == 1) return a;
        long pp = pow(a, b / 2, m);
        pp *= pp;
        pp %= m;
        return (pp * (b % 2 == 0 ? 1 : a)) % m;
    }

    static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        MyScanner(BufferedReader br) {
            this.br = br;
        }

        public MyScanner(InputStream in) {
            this(new BufferedReader(new InputStreamReader(in)));
        }

        void findToken() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        String next() {
            findToken();
            return st.nextToken();
        }

        Integer[] nab(int n) {
            Integer[] k = new Integer[n];
            for (int i = 0; i < n; i++) {
                k[i] = sc.fi();
            }
            return k;
        }

        int[] na(int n) {
            int[] k = new int[n];
            for (int i = 0; i < n; i++) {
                k[i] = sc.fi();
            }
            return k;
        }

        long[] nl(int n) {
            long[] k = new long[n];
            for (int i = 0; i < n; i++) {
                k[i] = sc.nextLong();
            }
            return k;
        }

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

        int fi() {
            String t = next();
            int cur = 0;
            boolean n = t.charAt(0) == '-';
            for (int a = n ? 1 : 0; a < t.length(); a++) {
                cur = cur * 10 + t.charAt(a) - '0';
            }
            return n ? -cur : cur;
        }

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

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

}