import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	private static Scanner in;
	private static PrintWriter out;
	private static final int MOD = (int)1e9 + 7;

	private static int n;
	private static int[] a, degIn;
	private static ArrayList<Integer> s, t;
	private static boolean[] visited;
	private static ArrayList<Integer>[] graph;

	private static boolean isSubset(int a, int b) {
		return (a & b) == a;
	}

	private static boolean isIntersect(int a, int b) {
		return (a & b) != 0;
	}

	// Solve for each weakly connected component (WCC)
	private static int cntOrder(ArrayList<Integer> s, ArrayList<Integer> t) {
		int p = s.size(), m = t.size();

		int[] inMask = new int[m];
		for(int x = 0; x < p; ++x)
			for(int i = 0; i < m; ++i)
				if (t.get(i) % s.get(x) == 0)
					inMask[i] |= 1 << x;

		int[] cnt = new int[1<<p];
		for(int mask = 0; mask < (1<<p); ++mask)
			for(int i = 0; i < m; ++i)
				if (isSubset(inMask[i], mask))
					++cnt[mask];

		int[][] dp = new int[m+1][1<<p];
		for(int i = 0; i < m; ++i)
			dp[1][inMask[i]] += 1;
		for(int k = 1; k < m; ++k) {
			for(int mask = 0; mask < (1<<p); ++mask) {
				for(int i = 0; i < m; ++i)
					if (!isSubset(inMask[i], mask) && isIntersect(inMask[i], mask))
						dp[k+1][mask | inMask[i]] = (int)((dp[k+1][mask | inMask[i]] + dp[k][mask]) % MOD);
				dp[k+1][mask] = (int)((dp[k+1][mask] + (long)dp[k][mask] * (cnt[mask] - k)) % MOD);
			}
		}

		return dp[m][(1<<p)-1];
	}

	private static void dfs(int u) {
		visited[u] = true;
		if (degIn[u] == 0)
			s.add(a[u]);
		else
			t.add(a[u]);

		for(int v: graph[u])
			if (!visited[v])
				dfs(v);
	}

	private static void input() {
		n = in.nextInt();
		a = new int[n];
		for(int u = 0; u < n; ++u)
			a[u] = in.nextInt();
	}

	private static void solve() {
		// Pre-calculate C(n, k)
		int[][] c = new int[n][n];
		for(int i = 0; i < n; ++i) {
			c[i][0] = 1;
			for(int j = 1; j <= i; ++j)
				c[i][j] = (c[i-1][j-1] + c[i-1][j]) % MOD;
		}

		// Building divisibility graph
		degIn = new int[n];
		graph = new ArrayList[n];
		for(int u = 0; u < n; ++u)
			graph[u] = new ArrayList<>();
		for(int u = 0; u < n; ++u) {
			for(int v = 0; v < n; ++v) {
				if (u != v && a[v] % a[u] == 0) {
					graph[u].add(v);
					graph[v].add(u);
					++degIn[v];
				}
			}
		}

		// Solve for each WCC of divisibility graph and combine result
		int ans = 1;
		int curLen = 0;
		visited = new boolean[n];
		for(int u = 0; u < n; ++u) {
			if (!visited[u]) {
				s = new ArrayList<>();
				t = new ArrayList<>();
				dfs(u);

				if (!t.isEmpty()) {
					int sz = t.size() - 1;
					int cnt = cntOrder(s, t);

					// Number of orders for current WCC
					ans = (int)(((long)ans * cnt) % MOD);
					// Number of ways to insert <sz> number to array of <curLen> elements
					ans = (int)(((long)ans * c[curLen + sz][sz]) % MOD);
					curLen += sz;
				}
			}
		}

		out.println(ans);
	}

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

		input();
		solve();

		out.close();
	}
}


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

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

    static final class TaskF {
        public void solve(int __, InputReader in, PrintWriter out) {
            String s = in.next();
            String t = in.next();
            int[][] result = solve(s.toCharArray(), t.toCharArray());
            out.println(result.length);
            for (int[] pair : result) {
                out.print(pair[0]);
                out.print(' ');
                out.println(pair[1]);
            }
        }

        private int[][] solve(char[] s, char[] t) {
            int[][] result = solveInternal(s, t);
            int[][] anotherResult = solveInternal(t, s);
            if (anotherResult.length < result.length) {
                result = anotherResult;
                for (int[] pair : result) {
                    ArrayUtils.swap(pair, 0, 1);
                }
            }
            return result;
        }

        private int[][] solveInternal(char[] s, char[] t) {
            List<Integer> sChangings = getChangings(s, 0, s.length, s, 0, 0, 'a');
            List<Integer> tChangings = getChangings(t, 0, t.length, t, 0, 0, 'b');
            int[][] result = solveGreedy(s, 0, s.length, s, 0, 0, t, 0, t.length, t, 0, 0, 0, Integer.MAX_VALUE);
            assert result != null;
            int balance = (sChangings.size() - tChangings.size()) / 2;
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    int sp = (balance > 0 ? balance : 0) + i;
                    int tp = (balance < 0 ? -balance : 0) + j;
                    if ((sp != 0 && sp >= sChangings.size()) || (tp != 0 && tp >= tChangings.size())) continue;
                    int sSep = sp < sChangings.size() ? sChangings.get(sp) : 0;
                    int tSep = tp < tChangings.size() ? tChangings.get(tp) : 0;
                    int[][] current = solveGreedy(t, 0, tSep, s, sSep, s.length, s, 0, sSep, t, tSep, t.length, 1, result.length);
                    if (current != null) {
                        result = current;
                        current[0][0] = sSep;
                        current[0][1] = tSep;
                    }
                }
            }
            return result;
        }

        private int[][] solveGreedy(char[] s1, int s1from, int s1to,
                                    char[] s2, int s2from, int s2to,
                                    char[] t1, int t1from, int t1to,
                                    char[] t2, int t2from, int t2to,
                                    int offset, int limit) {
            List<Integer> ss = getChangings(s1, s1from, s1to, s2, s2from, s2to, 'a');
            List<Integer> tt = getChangings(t1, t1from, t1to, t2, t2from, t2to, 'b');
            int length = Math.max(ss.size(), tt.size());
            if (offset + length >= limit) {
                return null;
            }
            int[][] result = new int[offset + length][2];
            for (int i = 0; i < length; ++i) {
                result[offset + i][0] = pop(ss);
                result[offset + i][1] = pop(tt);
                List<Integer> tmp = ss;
                ss = tt;
                tt = tmp;
            }
            return result;
        }

        private List<Integer> getChangings(char[] s1, int s1from, int s1to, char[] s2, int s2from, int s2to, char target) {
            List<Integer> changings = new ArrayList<>();
            for (int i = s2to; i-- > s2from; ) {
                char current = s2[i];
                if (current != target) {
                    changings.add(s1to - s1from + i - s2from + 1);
                    target = current;
                }
            }
            for (int i = s1to; i-- > s1from; ) {
                char current = s1[i];
                if (current != target) {
                    changings.add(i - s1from + 1);
                    target = current;
                }
            }
            Collections.reverse(changings);
            return changings;
        }

        private static int pop(List<Integer> stack) {
            return stack.isEmpty() ? 0 : stack.remove(stack.size() - 1);
        }

    }

    static class InputReader {
        private final BufferedReader reader;
        private StringTokenizer tokenizer;

        public InputReader(InputStream in) {
            reader = new BufferedReader(new InputStreamReader(in));
        }

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

        public String readLine() {
            String line;
            try {
                line = reader.readLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return line;
        }

    }

    static class ArrayUtils {
        private ArrayUtils() {
        }

        public static void swap(int[] array, int i, int j) {
            int tmp = array[i];
            array[i] = array[j];
            array[j] = tmp;
        }

    }
}


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

public class Crocodile implements Runnable {
    private void solve() throws IOException {
        int m = nextInt();
        int n = nextInt();
        int mx = Math.max(n, m);
        double[][] ans = new double[mx + 1][mx + 1];
        for (int sum = 0; sum <= mx + mx; ++sum) {
            for (int a = 0; a <= mx; ++a) {
                int b = sum - a;
                if (b >= 0 && b <= mx) {
                    ans[a][b] = doit(a, b, ans);
                }
            }
        }
        writer.println(ans[m][n] + " " + (1.0 - ans[m][n]));
    }

    private double doit(int m, int n, double[][] ans) {
        double res = 1.0 / (n + 1);
        if (m == 0 || n == 0) return res;
        double borderP = 1 / (ans[n][m - 1] * (n + 1) + 1);
        res = Math.max(res, eval(m, n, ans, 0.0));
        res = Math.max(res, eval(m, n, ans, borderP));
        res = Math.max(res, eval(m, n, ans, 1.0));
        return res;
    }

    private double eval(int m, int n, double[][] ans, double p) {
        return (1 - p) * n / (n + 1.0) * (1 - ans[n - 1][m]) + (p + (1 - p) / (n + 1.0) - Math.max((1 - p) / (n + 1), p * ans[n][m - 1]));
    }

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

    BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter writer;

    public void run() {
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            writer = new PrintWriter(System.out);
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

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

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

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

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


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

import static java.lang.Math.*;

public class Main implements Runnable
{
    static class InputReader
    {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

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

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

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

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

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

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

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

            int sgn = 1;

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

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

            while (!isSpaceChar(c));

            return res * sgn;
        }

        public long nextLong()
        {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;

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

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

        public double nextDouble()
        {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-')
            {
                sgn = -1;
                c = read();
            }

            double res = 0;
            while (!isSpaceChar(c) && c != '.')
            {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }

            if (c == '.')
            {
                c = read();
                double m = 1;
                while (!isSpaceChar(c))
                {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }

            return res * sgn;
        }

        public String readString()
        {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do
            {
                res.appendCodePoint(c);
                c = read();
            }

            while (!isSpaceChar(c));

            return res.toString();
        }

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

        public String next()
        {
            return readString();
        }

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

    public static void main(String args[]) throws Exception
    {
        new Thread(null, new Main(),"Main",1<<27).start();
    }

    public void run()
    {
        InputReader sc = new InputReader(System.in);
        PrintWriter w = new PrintWriter(System.out);

        int t = sc.nextInt();

        for(int x = 0; x < t; x++)
        {
            int n = sc.nextInt();

            int weight[][] = new int[n][n];
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < n; j++)
                    weight[i][j] = sc.nextInt();
            }

            w.println("B");
            w.flush();

            char type = sc.next().charAt(0);
            int node = sc.nextInt() - 1;

            int situation = 0;
            if(node >= n)
                situation ^= 1;

            if(type == 'D')
            {
                situation ^= 1;
            }

            int preferences[][] = new int[2 * n][n];

            if(situation == 0)
            {
                for(int i = 0; i < n; ++i)
                {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j)
                    {
                        p[j] = new Pair(n + j, weight[i][j]);
                    }

                    Arrays.sort(p, new Comparator<Pair>()
                    {
                        public int compare(Pair p1, Pair p2)
                        {
                            return p1.val - p2.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[i][j] = p[j].ind;
                }

                for(int i = 0; i < n; ++i)
                {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j)
                    {
                        p[j] = new Pair(j, weight[j][i]);
                    }

                    Arrays.sort(p, new Comparator<Pair>()
                    {
                        public int compare(Pair p1, Pair p2)
                        {
                            return p2.val - p1.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[n + i][j] = p[j].ind;
                }
            }
            else
            {
                for(int i = 0; i < n; ++i)
                {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j)
                    {
                        p[j] = new Pair(n + j, weight[i][j]);
                    }

                    Arrays.sort(p, new Comparator<Pair>()
                    {
                        public int compare(Pair p1, Pair p2)
                        {
                            return p2.val - p1.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[i][j] = p[j].ind;
                }

                for(int i = 0; i < n; ++i)
                {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j)
                    {
                        p[j] = new Pair(j, weight[j][i]);
                    }

                    Arrays.sort(p, new Comparator<Pair>()
                    {
                        public int compare(Pair p1, Pair p2)
                        {
                            return p1.val - p2.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[n + i][j] = p[j].ind;
                }
            }

            int match[] = StableMarriage.findStableMarriage(preferences);
            while(node != -2)
            {
                w.println((match[node] + 1));
                w.flush();
                node = sc.nextInt() - 1;
            }
        }

        w.close();
    }
}

class Pair
{
    int ind, val;
    Pair(int a, int b)
    {
        ind = a;
        val = b;
    }
}

class StableMarriage
{
    static int[] findStableMarriage(int[][] preferences)
    {
        int n = preferences.length / 2;

        int[] match = new int[2 * n];
        Arrays.fill(match, -1);

        int rank[][] = new int[n][n];
        for(int j = n; j < 2 * n; ++j)
        {
            for(int i = 0; i < n; ++i)
            {
                rank[j - n][preferences[j][i]] = i;
            }
        }

        Queue<Integer> notMatched = new LinkedList<>();
        for(int i = 0; i < n; ++i)
            notMatched.add(i);

        int nextRankToBeProposed[] = new int[n];

        while(!notMatched.isEmpty())
        {
            int ind = notMatched.poll();

            while(true)
            {
                int j = preferences[ind][nextRankToBeProposed[ind]++];

                if(match[j] == -1)
                {
                    match[ind] = j;
                    match[j] = ind;
                    break;
                }
                else if(rank[j - n][match[j]] > rank[j - n][ind])
                {
                    match[match[j]] = -1;
                    notMatched.add(match[j]);
                    match[ind] = j;
                    match[j] = ind;
                    break;
                }
            }
        }

        return match;
    }

    static boolean stable(int[][] preferences, int[] match)
    {
        int n = match.length / 2;

        for(int i = 0; i < n; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(match[i] == j + n)
                    continue;

                int flag = 0;
                for(int k = 0; k < n; ++k)
                {
                    if(preferences[i][k] == match[i])
                        break;

                    if(preferences[i][k] == j + n)
                    {
                        flag++;
                        break;
                    }
                }

                for(int k = 0; k < n; ++k)
                {
                    if(preferences[j + n][k] == match[j + n])
                        break;

                    if(preferences[j + n][k] == i)
                    {
                        flag++;
                        break;
                    }
                }

                if(flag == 2)
                    return false;
            }
        }

        return true;
    }
}


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

import static java.lang.Math.*;

public class Main implements Runnable {
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

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

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

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

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

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        public int nextInt() {
            int c = read();

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

            int sgn = 1;

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

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

            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;

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

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public String readString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            }
            while (!isSpaceChar(c));

            return res.toString();
        }

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

        public String next() {
            return readString();
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
    public static void main(String args[]) throws Exception {
        new Thread(null, new Main(),"Main",1<<27).start();
    }
    public void run() {
        InputReader sc = new InputReader(System.in);
        PrintWriter w = new PrintWriter(System.out);

        int t = sc.nextInt();

        for(int x = 0; x < t; x++) {
            int n = sc.nextInt();

            int weight[][] = new int[n][n];
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < n; ++j)
                    weight[i][j] = sc.nextInt();
            }

            w.println("B");
            w.flush();

            char type = sc.next().charAt(0);
            int node = sc.nextInt() - 1;

            int situation = 0;
            if(node >= n)
                situation ^= 1;

            if(type == 'D') {
                situation ^= 1;
            }

            int preferences[][] = new int[2 * n][n];

            if(situation == 0) {
                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(n + j, weight[i][j]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p1.val - p2.val;
                        }
                    });
                    for(int j = 0; j < n; ++j)
                        preferences[i][j] = p[j].ind;
                }

                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(j, weight[j][i]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p2.val - p1.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[n + i][j] = p[j].ind;
                }
            }
            else {
                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(n + j, weight[i][j]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p2.val - p1.val;
                        }
                    });
                    for(int j = 0; j < n; ++j)
                        preferences[i][j] = p[j].ind;
                }

                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(j, weight[j][i]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p1.val - p2.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[n + i][j] = p[j].ind;
                }
            }

            int match[] = StableMarriage.findStableMarriage(preferences);
            while(node != -2) {
                w.println((match[node] + 1));
                w.flush();
                node = sc.nextInt() - 1;
            }
        }

        w.close();
    }
}
class Pair {
    int ind, val;
    Pair(int a, int b) {
        ind = a;
        val = b;
    }
}
class StableMarriage {
    static int[] findStableMarriage(int[][] preferences) {
        // Also known as Gale-Shapley algorithm

        // 0 - (n - 1) ids are man, rest are woman
        // preferences is a 2n (first n man and last n woman) x n matrix which gives person id's sorted rank wise
        // match is an array of size 2*n - matched person for each id

        int n = preferences.length / 2;

        int[] match = new int[2 * n];
        Arrays.fill(match, -1);

        // A rank matrix of n x n, determines rank of each man for each woman
        int rank[][] = new int[n][n];
        for(int j = n; j < 2 * n; ++j) {
            for(int i = 0; i < n; ++i) {
                rank[j - n][preferences[j][i]] = i;
            }
        }

        Queue<Integer> notMatched = new LinkedList<>();
        for(int i = 0; i < n; ++i)
            notMatched.add(i);

        int nextRankToBeProposed[] = new int[n];

        while(!notMatched.isEmpty()) {
            int ind = notMatched.poll(); // current man who will propose

            while(true) {
                int j = preferences[ind][nextRankToBeProposed[ind]++]; // woman to be proposed

                if(match[j] == -1) { // if woman not matched yet
                    match[ind] = j;
                    match[j] = ind;
                    break;
                }
                else if(rank[j - n][match[j]] > rank[j - n][ind]) { // if this man more preferable
                    match[match[j]] = -1;
                    notMatched.add(match[j]); // previous man needs to propose again
                    match[ind] = j;
                    match[j] = ind;
                    break;
                }
            }
        }

        // if(!stable(preferences, match))
        //     System.out.println("Wrong code");

        return match;
    }
    static boolean stable(int[][] preferences, int[] match) {
        int n = match.length / 2;

        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                if(match[i] == j + n)
                    continue;

                int flag = 0;
                for(int k = 0; k < n; ++k) {
                    if(preferences[i][k] == match[i])
                        break;

                    if(preferences[i][k] == j + n) {
                        flag++;
                        break;
                    }
                }
                for(int k = 0; k < n; ++k) {
                    if(preferences[j + n][k] == match[j + n])
                        break;

                    if(preferences[j + n][k] == i) {
                        flag++;
                        break;
                    }
                }
                if(flag == 2)
                    return false;
            }
        }

        return true;
    }
}


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

import static java.lang.Math.*;

public class Main implements Runnable {
    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private SpaceCharFilter filter;
        private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

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

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

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

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

        public String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
        public int nextInt() {
            int c = read();

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

            int sgn = 1;

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

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

            return res * sgn;
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;

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

        public double nextDouble() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            double res = 0;
            while (!isSpaceChar(c) && c != '.') {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, nextInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            }
            if (c == '.') {
                c = read();
                double m = 1;
                while (!isSpaceChar(c)) {
                    if (c == 'e' || c == 'E')
                        return res * Math.pow(10, nextInt());
                    if (c < '0' || c > '9')
                        throw new InputMismatchException();
                    m /= 10;
                    res += (c - '0') * m;
                    c = read();
                }
            }
            return res * sgn;
        }

        public String readString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            }
            while (!isSpaceChar(c));

            return res.toString();
        }

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

        public String next() {
            return readString();
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
    }
    public static void main(String args[]) throws Exception {
        new Thread(null, new Main(),"Main",1<<27).start();
    }
    public void run() {
        InputReader sc = new InputReader(System.in);
        PrintWriter w = new PrintWriter(System.out);

        int t = sc.nextInt();

        for(int x = 0; x < t; ++x) {
            int n = sc.nextInt();

            int weight[][] = new int[n][n];
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < n; ++j)
                    weight[i][j] = sc.nextInt();
            }

            w.println("B");
            w.flush();

            char type = sc.next().charAt(0);
            int node = sc.nextInt() - 1;

            int situation = 0;
            if(node >= n)
                situation ^= 1;

            if(type == 'D') {
                situation ^= 1;
            }

            int preferences[][] = new int[2 * n][n];

            if(situation == 0) {
                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(n + j, weight[i][j]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p1.val - p2.val;
                        }
                    });
                    for(int j = 0; j < n; ++j)
                        preferences[i][j] = p[j].ind;
                }

                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(j, weight[j][i]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p2.val - p1.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[n + i][j] = p[j].ind;
                }
            }
            else {
                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(n + j, weight[i][j]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p2.val - p1.val;
                        }
                    });
                    for(int j = 0; j < n; ++j)
                        preferences[i][j] = p[j].ind;
                }

                for(int i = 0; i < n; ++i) {
                    Pair p[] = new Pair[n];
                    for(int j = 0; j < n; ++j) {
                        p[j] = new Pair(j, weight[j][i]);
                    }
                    Arrays.sort(p, new Comparator<Pair>() {
                        public int compare(Pair p1, Pair p2) {
                            return p1.val - p2.val;
                        }
                    });

                    for(int j = 0; j < n; ++j)
                        preferences[n + i][j] = p[j].ind;
                }
            }

            int match[] = StableMarriage.findStableMarriage(preferences);
            while(node != -2) {
                w.println((match[node] + 1));
                w.flush();
                node = sc.nextInt() - 1;
            }
        }

        w.close();
    }
}
class Pair {
    int ind, val;
    Pair(int a, int b) {
        ind = a;
        val = b;
    }
}
class StableMarriage {
    static int[] findStableMarriage(int[][] preferences) {
        // Also known as Gale-Shapley algorithm

        // 0 - (n - 1) ids are man, rest are woman
        // preferences is a 2n (first n man and last n woman) x n matrix which gives person id's sorted rank wise
        // match is an array of size 2*n - matched person for each id

        int n = preferences.length / 2;

        int[] match = new int[2 * n];
        Arrays.fill(match, -1);

        // A rank matrix of n x n, determines rank of each man for each woman
        int rank[][] = new int[n][n];
        for(int j = n; j < 2 * n; ++j) {
            for(int i = 0; i < n; ++i) {
                rank[j - n][preferences[j][i]] = i;
            }
        }

        Queue<Integer> notMatched = new LinkedList<>();
        for(int i = 0; i < n; ++i)
            notMatched.add(i);

        int nextRankToBeProposed[] = new int[n];

        while(!notMatched.isEmpty()) {
            int ind = notMatched.poll(); // current man who will propose

            while(true) {
                int j = preferences[ind][nextRankToBeProposed[ind]++]; // woman to be proposed

                if(match[j] == -1) { // if woman not matched yet
                    match[ind] = j;
                    match[j] = ind;
                    break;
                }
                else if(rank[j - n][match[j]] > rank[j - n][ind]) { // if this man more preferable
                    match[match[j]] = -1;
                    notMatched.add(match[j]); // previous man needs to propose again
                    match[ind] = j;
                    match[j] = ind;
                    break;
                }
            }
        }

        // if(!stable(preferences, match))
        //     System.out.println("Wrong code");

        return match;
    }
    static boolean stable(int[][] preferences, int[] match) {
        int n = match.length / 2;

        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                if(match[i] == j + n)
                    continue;

                int flag = 0;
                for(int k = 0; k < n; ++k) {
                    if(preferences[i][k] == match[i])
                        break;

                    if(preferences[i][k] == j + n) {
                        flag++;
                        break;
                    }
                }
                for(int k = 0; k < n; ++k) {
                    if(preferences[j + n][k] == match[j + n])
                        break;

                    if(preferences[j + n][k] == i) {
                        flag++;
                        break;
                    }
                }
                if(flag == 2)
                    return false;
            }
        }

        return true;
    }
}


import java.io.InputStreamReader;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
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();
    }
}

class TaskD {
    static class Point {
        int x;
        int y;
        int z;

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

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Point point = (Point) o;

            if (x != point.x) return false;
            if (y != point.y) return false;
            if (z != point.z) return false;

            return true;
        }

        public int hashCode() {
            int result = x;
            result = 31 * result + y;
            result = 31 * result + z;
            return result;
        }
    }

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        Point[][] ans = new Point[51][];
        ans[1] = new Point[]{new Point(0, 0, 0)};
        ans[2] = new Point[]{new Point(0, 0, 0), new Point(0, 1, 0), new Point(1, 1, 0), new Point(1, 0, 0), new Point(1, 0, 1), new Point(1, 1, 1), new Point(0, 1, 1), new Point(0, 0, 1)};
        for (int n = 3; n < ans.length; ++n) {
            Point[] prev = ans[n - 1];
            int prevSize = (n - 1) * (n - 1) * (n - 1);
            if (prev.length != prevSize) throw new RuntimeException();
            int sideSize = (n - 1) * (n - 1);
            if (!prev[prevSize - sideSize - 1].equals(new Point(n - 2, 0, n - 3))) throw new RuntimeException();
            if (!prev[prevSize - sideSize].equals(new Point(n - 2, 0, n - 2))) throw new RuntimeException();
            if (!prev[prevSize - 1].equals(new Point(0, 0, n - 2))) throw new RuntimeException();
            if (!prev[0].equals(new Point(0, 0, 0))) throw new RuntimeException();
            Point[] cur = new Point[n * n * n];
            ans[n] = cur;
            int curPtr = 0;
            for (int i = 0; i < sideSize; ++i) {
                Point old = prev[prevSize - 1 - i];
                cur[curPtr++] = new Point(old.x, old.y, 0);
            }
            for (int i = 0; i < prevSize; ++i) {
                Point old = prev[i];
                cur[curPtr++] = new Point(n - 2 - old.x, old.y, old.z + 1);
            }
            Point[] rect = getRectangleTraversal(n - 1, n);
            for (int i = 0; i < rect.length; ++i) {
                cur[curPtr++] = new Point(n - 1, rect[i].x, rect[i].y);
            }
            rect = getRectangleTraversal2(n);
            for (int i = 0; i < rect.length; ++i) {
                cur[curPtr++] = new Point(rect[i].x, n - 1, rect[i].y);
            }
            if (curPtr != cur.length) throw new RuntimeException();
            for (int i = 0; i < cur.length; ++i) {
                int tmp = cur[i].y;
                cur[i].y = cur[i].z;
                cur[i].z = tmp;
            }
        }
        int n = in.nextInt();
        int[][][] field = new int[n][n][n];
        Point prev = null;
        int at = 0;
        for (Point p : ans[n]) {
            if (prev != null) {
                int d = Math.abs(p.x - prev.x) + Math.abs(p.y - prev.y) + Math.abs(p.z - prev.z);
                if (d != 1) throw new RuntimeException();
            }
            prev = p;
            ++at;
            if (field[p.x][p.y][p.z] != 0) throw new RuntimeException();
            field[p.x][p.y][p.z] = at;
        }
        boolean xf = true;
        for (int[][] x : field) {
            if (xf) xf = false; else out.println();
            for (int[] y : x) {
                boolean zf = true;
                for (int z : y) {
                    if (zf) zf = false; else out.print(" ");
                    if (z == 0) throw new RuntimeException();
                    out.print(z);
                }
                out.println();
            }
        }
    }

    private Point[] getRectangleTraversal2(int n) {
        int sx = n;
        int sy = n;
        Point[] res = new Point[sx * sy];
        int resPtr = 0;
        if (sy % 2 == 0) {
            for (int y = sy - 1; y >= 0; --y) {
                if (y % 2 != 0) {
                    for (int x = 0; x < sx; ++x)
                        res[resPtr++] = new Point(y, x, 0);
                } else {
                    for (int x = sx - 1; x >= 0; --x)
                        res[resPtr++] = new Point(y, x, 0);
                }
            }
        } else {
            for (int y = sy - 1; y >= 2; --y) {
                if (y % 2 == 0) {
                    for (int x = 0; x < sx; ++x)
                        res[resPtr++] = new Point(y, x, 0);
                } else {
                    for (int x = sx - 1; x >= 0; --x)
                        res[resPtr++] = new Point(y, x, 0);
                }
            }
            for (int x = sx - 1; x >= 0; --x) {
                if (x % 2 == 0) {
                    res[resPtr++] = new Point(1, x, 0);
                    res[resPtr++] = new Point(0, x, 0);
                } else {
                    res[resPtr++] = new Point(0, x, 0);
                    res[resPtr++] = new Point(1, x, 0);
                }
            }
        }
        if (resPtr != res.length) throw new RuntimeException();
        return res;
    }

    private Point[] getRectangleTraversal(int sx, int sy) {
        Point[] res = new Point[sx * sy];
        int resPtr = 0;
        if (sy % 2 != 0) {
            for (int y = sy - 1; y >= 0; --y) {
                if (y % 2 == 0) {
                    for (int x = 0; x < sx; ++x)
                        res[resPtr++] = new Point(x, y, 0);
                } else {
                    for (int x = sx - 1; x >= 0; --x)
                        res[resPtr++] = new Point(x, y, 0);
                }
            }
        } else {
            for (int y = sy - 1; y >= 2; --y) {
                if (y % 2 != 0) {
                    for (int x = 0; x < sx; ++x)
                        res[resPtr++] = new Point(x, y, 0);
                } else {
                    for (int x = sx - 1; x >= 0; --x)
                        res[resPtr++] = new Point(x, y, 0);
                }
            }
            for (int x = 0; x < sx; ++x) {
                if (x % 2 == 0) {
                    res[resPtr++] = new Point(x, 1, 0);
                    res[resPtr++] = new Point(x, 0, 0);
                } else {
                    res[resPtr++] = new Point(x, 0, 0);
                    res[resPtr++] = new Point(x, 1, 0);
                }
            }
        }
        if (resPtr != res.length) throw new RuntimeException();
        return res;
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        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 static java.lang.System.currentTimeMillis;

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

public class D {

    static void solve() throws IOException {
        // while (true) {
        // testWithVsWithout();
        // if (false) {
        // break;
        // }
        // }
        // test();
        int n = nextInt(), m = nextInt();
//      long time = currentTimeMillis();
        long answer = solve(n, m);
//      System.err.println(currentTimeMillis() - time);
        out.println(answer);
    }

    static void test() {
        for (int n = 1; n < 100; n++) {
            for (int m = 0; 2 * m <= n; m++) {
                long got = solve(n, m);
                long stup = solveStupid(n, m);
                if (got != stup) {
                    throw new AssertionError();
                }
            }
        }
        System.err.println("pass");
    }

    static void testWithVsWithout() {
        Random rng = new Random();
        int n = rng.nextInt(32001);
        while (n < 5) {
            n = rng.nextInt(32001);
        }
        int m = rng.nextInt(n / 2);
        long got = solve(n, m);
        long stup = solveWithoutOptimizations(n, m);
        if (got != stup) {
            throw new AssertionError();
        }
        System.err.println("pass");
    }

    private static long solve(int n, int m) {
        Point[] pointsLeft = new Point[n];
        Point[] pointsRight = new Point[n];
        for (int i = 0; i < n; i++) {
            pointsLeft[i] = new Point((i + 1) * 2, (i + 1) * 2);
            pointsRight[i] = new Point(4 * (n + 1) - (i + 1) * 2, (i + 1) * 2);
            // pointsLeft[i] = new Point((i+1) * 0.5, (i+1) * ok);
            // pointsRight[i] = new Point(n + 1 - (i+1) * 0.5, (i+1) * ok);
        }

        long answer = 0;

        int lastSegmentThing = m;

        int rightStop = n - m;

        for (int leftPointId = m; leftPointId + m < n; leftPointId++) {

            int segmentLeft = -1, segmentRight = -1;

            int xx, yy, theirDx, theirDy;
            long theirAbs, yyyy3;

            {
                int rightPointId = leftPointId;
                xx = pointsLeft[leftPointId].x + pointsRight[rightPointId].x >> 1;
                yy = pointsLeft[leftPointId].y + pointsRight[rightPointId].y >> 1;
                theirDx = xx - pointsLeft[leftPointId].x;
                theirDy = yy - pointsLeft[leftPointId].y;
                theirAbs = (long) theirDx * theirDx + (long) theirDy * theirDy
                        * 3;

                yyyy3 = (long) yy * yy * 3;

                for (int low = lastSegmentThing; low + m < n; low++) {
                    long lowX = 4 * (low + 1);
                    long dx = xx - lowX;
                    long abs = dx * dx + yyyy3;
                    if (abs < theirAbs) {
                        segmentLeft = low;
                        break;
                    }
                }
            }

            // timeFirst += currentTimeMillis();
            int yyyy3i = (int) yyyy3;
            int theirAbsi = (int) theirAbs;
            if (segmentLeft < 0) {
                break;
            }
            lastSegmentThing = segmentLeft;

            segmentRight = n - 1 - segmentLeft;

            answer += segmentRight - segmentLeft + 1;

            int dx;

            int yyyy3MinusTheirAbsi = yyyy3i - theirAbsi;

            int curAddInt = 0;

            for (int rightPointId = leftPointId + 1; rightPointId < rightStop; rightPointId++) {
                --xx;
                ++yy;
                // xx = pointsLeft[leftPointId].x + pointsRight[rightPointId].x
                // >> 1;
                // yy = pointsLeft[leftPointId].y + pointsRight[rightPointId].y
                // >> 1;
                --theirDx;
                ++theirDy;
                // theirDx = xx - pointsLeft[leftPointId].x;
                // theirDy = yy - pointsLeft[leftPointId].y;
                yyyy3MinusTheirAbsi += 2 * theirDx + 1;
                yyyy3MinusTheirAbsi -= 6 * theirDy - 3;
                // theirAbs = theirDx * theirDx + theirDy * theirDy * 3;
                yyyy3MinusTheirAbsi += 6 * yy - 3;
                // if (yyyy3 > Integer.MAX_VALUE) {
                // System.err.println(yyyy3);
                // }
                // long yyyy3 = yy * yy * 3;
                // if (segmentLeft < lastLeftForThisRight[rightPointId]) {
                // segmentLeft = lastLeftForThisRight[rightPointId];
                // }
                // if(segmentRight > lastRightForThisRight[rightPointId]) {
                // segmentRight = lastRightForThisRight[rightPointId];
                // }
                int lowX = 4 * (segmentLeft + 1);
                dx = xx - lowX;
                int abs = dx * dx + yyyy3MinusTheirAbsi;
                while (segmentLeft <= segmentRight) {
                    // if (dx * dx > Integer.MAX_VALUE) {
                    // System.err.println(dx * dx);
                    // }
                    if (abs < 0) {
                        break;
                    } else {
                        ++segmentLeft;
                        abs -= 8 * dx - 16;
                        dx -= 4;
                    }
                }

                lowX = 4 * (segmentRight + 1);
                dx = (xx - lowX);
                abs = dx * dx + yyyy3MinusTheirAbsi;

                while (segmentLeft <= segmentRight) {
                    if (abs < 0) {
                        break;
                    } else {
                        --segmentRight;
                        abs += 8 * dx + 16;
                        dx += 4;
                    }
                }

                if (segmentLeft > segmentRight) {
                    rightStop = rightPointId;
                    break;
                }
                curAddInt += segmentRight - segmentLeft + 1;
            }
            answer += 2L * curAddInt;
        }

        // System.err.println("time first: "+timeFirst);
        // System.err.println("time second: "+timeSecond);
        return answer * 3L;
    }

    private static long solveWithoutOptimizations(int n, int m) {
        Point[] pointsLeft = new Point[n];
        Point[] pointsRight = new Point[n];
        for (int i = 0; i < n; i++) {
            pointsLeft[i] = new Point((i + 1) * 2, (i + 1) * 2);
            pointsRight[i] = new Point(4 * (n + 1) - (i + 1) * 2, (i + 1) * 2);
        }

        long answer = 0;

        int lastSegmentThing = m;

        for (int leftPointId = m; leftPointId + m < n; leftPointId++) {

            int segmentLeft = -1, segmentRight = -1;
            {
                int rightPointId = leftPointId;
                long xx = pointsLeft[leftPointId].x
                        + pointsRight[rightPointId].x >> 1;
                long yy = pointsLeft[leftPointId].y
                        + pointsRight[rightPointId].y >> 1;
                long theirDx = xx - pointsLeft[leftPointId].x;
                long theirDy = yy - pointsLeft[leftPointId].y;
                long theirAbs = theirDx * theirDx + (long) theirDy * theirDy
                        * 3;

                for (int low = lastSegmentThing; low + m < n; low++) {
                    long lowX = 4 * (low + 1);
                    long dx = xx - lowX;
                    long abs = dx * dx + yy * yy * 3;
                    if (abs < theirAbs) {
                        segmentLeft = low;
                        break;
                    }
                }
            }

            if (segmentLeft < 0) {
                break;
            }
            lastSegmentThing = segmentLeft;

            segmentRight = n - 1 - segmentLeft;

            answer += segmentRight - segmentLeft + 1;

            for (int rightPointId = leftPointId + 1; rightPointId < n - m; rightPointId++) {
                long xx = pointsLeft[leftPointId].x
                        + pointsRight[rightPointId].x >> 1;
                long yy = pointsLeft[leftPointId].y
                        + pointsRight[rightPointId].y >> 1;
                long theirDx = xx - pointsLeft[leftPointId].x;
                long theirDy = yy - pointsLeft[leftPointId].y;
                long theirAbs = theirDx * theirDx + theirDy * theirDy * 3;
                while (segmentLeft <= segmentRight) {
                    long lowX = 4 * (segmentLeft + 1);
                    long dx = xx - lowX;
                    long abs = dx * dx + yy * yy * 3;
                    if (abs < theirAbs) {
                        break;
                    } else {
                        ++segmentLeft;
                    }
                }

                while (segmentLeft <= segmentRight) {
                    long lowX = 4 * (segmentRight + 1);
                    long dx = xx - lowX;
                    long abs = dx * dx + yy * yy * 3;
                    if (abs < theirAbs) {
                        break;
                    } else {
                        --segmentRight;
                    }
                }

                if (segmentLeft > segmentRight) {
                    break;
                }
                answer += 2 * (segmentRight - segmentLeft + 1);
            }
        }

        return answer * 3L;
    }

    static long solveStupid(int n, int m) {
        Point[] pointsLeft = new Point[n];
        Point[] pointsRight = new Point[n];
        // double ok = Math.sqrt(3) * 0.5;
        for (int i = 0; i < n; i++) {
            pointsLeft[i] = new Point((i + 1) * 2, (i + 1) * 2);
            pointsRight[i] = new Point(4 * (n + 1) - (i + 1) * 2, (i + 1) * 2);
            // pointsLeft[i] = new Point((i+1) * 0.5, (i+1) * ok);
            // pointsRight[i] = new Point(n + 1 - (i+1) * 0.5, (i+1) * ok);
        }

        long answer = 0;

        for (int leftPointId = m; leftPointId + m < n; leftPointId++) {

            for (int rightPointId = m; rightPointId + m < n; rightPointId++) {
                long xx = pointsLeft[leftPointId].x
                        + pointsRight[rightPointId].x >> 1;
                long yy = pointsLeft[leftPointId].y
                        + pointsRight[rightPointId].y >> 1;

                long theirDx = xx - pointsLeft[leftPointId].x;
                long theirDy = yy - pointsLeft[leftPointId].y;
                long theirAbs = theirDx * theirDx + theirDy * theirDy * 3;

                for (int low = m; low + m < n; low++) {
                    long lowX = 4 * (low + 1);
                    long dx = xx - lowX;
                    long abs = dx * dx + yy * yy * 3;
                    if (abs < theirAbs) {
                        ++answer;
                    }
                }
            }
        }

        return answer * 3L;
    }

    static class Point {
        final int x, y;

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

    static BufferedReader br;
    static StringTokenizer st;
    static PrintWriter out;

    public static void main(String[] args) throws IOException {
        InputStream input = System.in;
        PrintStream output = System.out;
        File file = new File("d.in");
        if (file.exists() && file.canRead()) {
            input = new FileInputStream(file);
        }
        br = new BufferedReader(new InputStreamReader(input));
        out = new PrintWriter(output);
        solve();
        out.close();
    }

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

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

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

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


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

public class E {
    public static ArrayList<Integer>[] g;
    public static boolean[] used;
    public static boolean[] cana;
    public static boolean[] canb;
    public static int a;
    public static int b;
    public static void dfs1(int node){
        used[node] = true;
        cana[node] = true;
        for(Integer n : g[node]){
            if(!used[n] && n != b){
                dfs1(n);
            }
        }
    }
    public static void dfs2(int node){
        used[node] = true;
        canb[node] = true;
        for(Integer n : g[node]){
            if(!used[n] && n != a){
                dfs2(n);
            }
        }
    }
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter writer = new PrintWriter(System.out);
        int t = Integer.parseInt(reader.readLine());
        for(int q = 0; q < t; ++q){
            StringTokenizer st = new StringTokenizer(reader.readLine());
            int n = Integer.parseInt(st.nextToken());
            g = new ArrayList[n];
            for(int i = 0; i < n; ++i){
                g[i] = new ArrayList<>();
            }
            cana = new boolean[n];
            canb = new boolean[n];
            int m = Integer.parseInt(st.nextToken());
            a = Integer.parseInt(st.nextToken()) - 1;
            b = Integer.parseInt(st.nextToken()) - 1;
            for(int i = 0; i < m; ++i){
                st = new StringTokenizer(reader.readLine());
                int x = Integer.parseInt(st.nextToken());
                int y = Integer.parseInt(st.nextToken());
                g[x - 1].add(y - 1);
                g[y - 1].add(x - 1);
            }
            used = new boolean[n];
            dfs1(a);
            used = new boolean[n];
            dfs2(b);
            cana[b] = true;
            canb[a] = true;
            long c1 = 0;
            long c2 = 0;
            for(int i = 0; i < n; ++i){
                if(!cana[i]){
                    ++c1;
                }
                if(!canb[i]){
                    ++c2;
                }
            }
            writer.println(c1 * c2);
        }
        writer.close();
    }
}


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

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

    static class FNezzarAndChocolateBars {
        static final int MAXN = 2048;

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            MOD2 mod = new MOD2();
            int[] fact = new int[MAXN];
            int[] ifact = new int[MAXN];
            fact[0] = ifact[0] = 1;
            for (int i = 1; i < MAXN; i++) {
                fact[i] = mod.multiply(fact[i - 1], i);
                ifact[i] = mod.inverse(fact[i]);
            }
            int n = in.nextInt(), k = in.nextInt();
            int[] l = in.readIntArray(n);
            int[][][] dp = new int[2][MAXN / k][MAXN / k];
            dp[1][0][0] = 1;
            int s = 0;

            for (int p = 0; p < n; p++) {
                int L = l[p];
                int invL = mod.inverse(L);
                int[] coeffs = new int[L / k + 1];
                int[] coeffs2 = new int[L / k + 1];
                for (int i = 0; i <= L / k; i++) {
                    if (k * i == L) continue;
                    int z = ifact[i];
                    if (i % 2 == 1) z = mod.subtract(0, z);
                    coeffs[i] = mod.multiply(z, mod.power(L - k * i, i));

                    if (i >= 1) {
                        coeffs2[i] = mod.multiply(z, mod.multiply(i, mod.power(L - k * i, i - 1)));
                    }
                }
                int r = p & 1;
                int h = r ^ 1;
                for (int i = 0; i <= s / k; i++) Arrays.fill(dp[r][i], 0);
                for (int i = 0; i <= s / k; i++)
                    for (int j = 0; j <= s / k; j++)
                        if (dp[h][i][j] != 0) {
                            int value = dp[h][i][j];
                            for (int t = 0; t <= L / k; t++) {
                                dp[r][i + t][j + t] = mod.add(dp[r][i + t][j + t], mod.multiply(value, coeffs[t]));
                                if (t > 0) {
                                    dp[r][i + t - 1][j + t] = mod.add(dp[r][i + t - 1][j + t], mod.multiply(value, coeffs2[t]));
                                }
                            }
                        }
                s += L;
            }
            int answer = 0;
            for (int i = 0; i <= s / k; i++)
                for (int j = 1; j <= s / k; j++) {
                    int value = dp[(n - 1) & 1][i][j];
                    int temp = mod.multiply(fact[i], mod.inverse(mod.power(k * j, i + 1)));
                    answer = mod.add(answer, mod.multiply(value, temp));
                }
            out.println(mod.multiply(mod.subtract(0, s), answer));
        }

    }

    static class MOD2 {
        static final int modulo = 998244353;

        public int add(int x, int y) {
            x += y;
            if (x >= modulo) x -= modulo;
            return x;
        }

        public int subtract(int x, int y) {
            x -= y;
            if (x < 0) x += modulo;
            return x;
        }

        public int multiply(int x, int y) {
            return (int) ((x * 1L * y) % modulo);
        }

        public int power(int x, long y) {
            int ans = 1;
            for (; y > 0; y >>= 1, x = (int) ((x * 1L * x) % modulo))
                if (y % 2 == 1) ans = (int) ((ans * 1L * x) % modulo);
            return ans;
        }

        public int inverse(int x) {
            return power(x, modulo - 2);
        }

    }

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

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

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

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

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

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

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

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

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

        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

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

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

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

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

    }
}


//package round93;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "WWWWWWWW\r\n" +
			"WBYWRBBY\r\n" +
			"BRYRBWYY\r\n" +
			"WWBRYWBB\r\n" +
			"BWWRWBYW\r\n" +
			"RBWRBWYY\r\n" +
			"WWWWWWWW\r\n" +
			"0 0 0 1\r\n" +
			"0 0 1\r\n" +
			"0 1\r\n" +
			"25";

	void solve()
	{
		b = new char[7][8];
		for(int i = 0;i < 7;i++){
			b[i] = ns(8);
		}
		int[] co = new int[10];
		for(int i = 0;i < 10;i++)co[i] = ni();

		String[] PILL = {
				"BY","BW","BR","BB",
				"RY","RW","RR",
				"WY","WW",
				"YY"
		};
		int[][] ctp = new int[10][26];
		for(int i = 0;i < 10;i++){
			for(int j = 0;j < 2;j++){
				ctp[i][PILL[i].charAt(j)-'A']++;
			}
		}

		int[][] C = new int[10][10];
		for(int i = 0;i < 10;i++){
			for(int j = 0;j < 10;j++){
				int tot = 0;
				for(int k = 0;k < 26;k++){
					tot += Math.min(ctp[i][k], ctp[j][k]);
				}
				C[i][j] = tot;
			}
		}

		map = new int[26*26];
		for(int i = 0;i < 10;i++){
			int f = PILL[i].charAt(0)-'A';
			int l = PILL[i].charAt(1)-'A';
			map[f*26+l] = i;
			map[l*26+f] = i;
		}
		used = new boolean[7][8];
		ct = new int[10];
		hist = new int[28];
		ctmap = new HashMap<Integer, Datum>();
		step = 0;

		rec(0, 0);

		int m = 10+100+10;
		int[] from = new int[m];
		int[] to = new int[m];
		int[] c = new int[m];
		int[] cap = new int[m];
		int O = 0;
		for(int i = 0;i < 10;i++){
			from[i+O] = 20; to[i+O] = i; c[i+O] = 0; cap[i+O] = 0; // Datum
		}
		O += 10;
		for(int i = 0;i < 10;i++){
			from[i+O] = i+10; to[i+O] = 21; c[i+O] = 0; cap[i+O] = co[i];
		}
		O += 10;
		for(int i = 0;i < 100;i++){
			from[i+O] = i/10; to[i+O] = i%10+10; c[i+O] = 2-C[i/10][i%10]; cap[i+O] = 999;
		}

		int[][][] cost = packWD(22, from, to, c);
		int[][][] capacity = packWD(22, from, to, cap);

		int mincost = 999;
		int[] opthist = null;
		int[][] optF = new int[10][10];
		for(Datum d : ctmap.values()){
			for(int i = 0;i < 10;i++){
				capacity[20][9-i][1] = d.ct[i];
			}
			int mc = solveMinCostFlow(cost, capacity, 20, 21, 28);
			if(mc < mincost){
				mincost = mc;
				opthist = d.hist;
				for(int i = 0;i < 10;i++){
					for(int j = 0;j < 10;j++){
						optF[i][j] = F[i][9-j][1];
					}
				}
			}
		}
//		tr(mincost);
//		tr(opthist);
//
//		int S = 0;
//		for(int i = 0;i < 10;i++){
//			for(int j = 0;j < 10;j++){
//				S += optF[i][j];
//			}
//		}
//		if(S != 28)throw new AssertionError(S);

		out.println(56-mincost);

		char[][] ret = new char[13][15];
		for(int i = 0;i < 13;i++){
			Arrays.fill(ret[i], '.');
		}

		for(int h : opthist){
			if(h < 64){
				// |
				int rr = h/8, cc = h%8;
				ret[rr*2+1][cc*2] = '|';

				int k = map[(b[rr][cc]-'A')*26+(b[rr+1][cc]-'A')];
				for(int i = 0;i < 10;i++){
					if(optF[k][i] > 0){
						if(flip(b[rr][cc], b[rr+1][cc], PILL[i].charAt(0), PILL[i].charAt(1))){
							ret[rr*2][cc*2] = PILL[i].charAt(1);
							ret[rr*2+2][cc*2] = PILL[i].charAt(0);
						}else{
							ret[rr*2][cc*2] = PILL[i].charAt(0);
							ret[rr*2+2][cc*2] = PILL[i].charAt(1);
						}
						optF[k][i]--;
						break;
					}
				}
			}else{
				h -= 64;
				// -
				int rr = h/8, cc = h%8;
				ret[rr*2][cc*2+1] = '-';

				int k = map[(b[rr][cc]-'A')*26+(b[rr][cc+1]-'A')];

				for(int i = 0;i < 10;i++){
					if(optF[k][i] > 0){
						if(flip(b[rr][cc], b[rr][cc+1], PILL[i].charAt(0), PILL[i].charAt(1))){
							ret[rr*2][cc*2] = PILL[i].charAt(1);
							ret[rr*2][cc*2+2] = PILL[i].charAt(0);
						}else{
							ret[rr*2][cc*2] = PILL[i].charAt(0);
							ret[rr*2][cc*2+2] = PILL[i].charAt(1);
						}
						optF[k][i]--;
						break;
					}
				}
			}
		}

		for(int i = 0;i < 13;i++){
			out.println(new String(ret[i]));
		}
	}

	static boolean flip(char a, char b, char c, char d)
	{
		int d1 = (a==c?1:0) + (b==d?1:0);
		int d2 = (a==d?1:0) + (b==c?1:0);
		return d2 > d1;
	}

	public static int[][][] packWD(int n, int[] from, int[] to, int[] w)
	{
		int[][][] g = new int[n][][];
		int[] p = new int[n];
		for(int f : from)p[f]++;
		for(int i = 0;i < n;i++)g[i] = new int[p[i]][2];
		for(int i = 0;i < from.length;i++){
			--p[from[i]];
			g[from[i]][p[from[i]]][0] = to[i];
			g[from[i]][p[from[i]]][1] = w[i];
		}
		return g;
	}

	int[][][] F;

	public int solveMinCostFlow(int[][][] cost, int[][][] capacity, int src, int sink, int all)
	{
		int n = cost.length;

		int[][][] flow = new int[n][][];
		for(int i = 0;i < n;i++) {
			flow[i] = new int[cost[i].length][2];
			for(int j = 0;j < cost[i].length;j++){
				flow[i][j][0] = cost[i][j][0];
			}
		}

		// unweighted invgraph
		// 逆グラフのcurのi番目=nextのとき、順グラフでcurはnextの何番目にあるかを返す
		int[][][] ig = new int[n][][];
		{
			int[] p = new int[n];
			for(int i = 0;i < n;i++){
				for(int j = 0;j < cost[i].length;j++)p[cost[i][j][0]]++;
			}
			for(int i = 0;i < n;i++)ig[i] = new int[p[i]][2];
			for(int i = n-1;i >= 0;i--){
				for(int j = 0;j < cost[i].length;j++){
					int u = --p[cost[i][j][0]];
					ig[cost[i][j][0]][u][0] = i;
					ig[cost[i][j][0]][u][1] = j;
				}
			}
		}

		int mincost = 0;
		int[] pot = new int[n]; // ポテンシャル

		final int[] d = new int[n];
		TreeSet<Integer> q = new TreeSet<Integer>(new Comparator<Integer>(){
			public int compare(Integer a, Integer b)
			{
				if(d[a] - d[b] != 0)return d[a] - d[b];
				return a - b;
			}
		});
		while(all > 0){
			// src~sinkの最短路を探す
			int[] prev = new int[n];
			int[] myind = new int[n];
			Arrays.fill(prev, -1);
			Arrays.fill(d, Integer.MAX_VALUE / 2);
			d[src] = 0;
			q.clear();
			q.add(src);
			while(!q.isEmpty()){
				int cur = q.pollFirst();
				if(cur == sink)break;
				for(int i = 0;i < cost[cur].length;i++) {
					int next = cost[cur][i][0];
					if(capacity[cur][i][1] - flow[cur][i][1] > 0){
						int nd = d[cur] + cost[cur][i][1] + pot[cur] - pot[next];
						if(d[next] > nd){
							q.remove(next);
							d[next] = nd;
							prev[next] = cur;
							myind[next] = i;
							q.add(next);
						}
					}
				}
				for(int i = 0;i < ig[cur].length;i++) {
					int next = ig[cur][i][0];
					int cind = ig[cur][i][1];
					if(flow[next][cind][1] > 0){
						int nd = d[cur] - cost[next][cind][1] + pot[cur] - pot[next];
						if(d[next] > nd){
							q.remove(next);
							d[next] = nd;
							prev[next] = cur;
							myind[next] = -cind-1;
							q.add(next);
						}
					}
				}
			}

			if(prev[sink] == -1)break;

			int minflow = all;
			int sumcost = 0;
			for(int i = sink;i != src;i = prev[i]){
				if(myind[i] >= 0){
					minflow = Math.min(minflow, capacity[prev[i]][myind[i]][1] - flow[prev[i]][myind[i]][1]);
					sumcost += cost[prev[i]][myind[i]][1];
				}else{
					// cur->next
					// prev[i]->i
					// iが持ってる
					// ig[cur][j][0]=nextのときg[next][ig[cur][j][1]] = cur
					int ind = -myind[i]-1;
//					tr(prev[i], ind);
					minflow = Math.min(minflow, flow[i][ind][1]);
					sumcost -= cost[i][ind][1];
				}
			}

			mincost += minflow * sumcost;
			for(int i = sink;i != src;i = prev[i]){
				if(myind[i] >= 0){
					flow[prev[i]][myind[i]][1] += minflow;
				}else{
					int ind = -myind[i]-1;
					flow[i][ind][1] -= minflow;
				}
			}
//			tr(flow);

			all -= minflow;
			for(int i = 0;i < n;i++){
				pot[i] += d[i];
			}
		}
		F = flow;
		return mincost;
	}

	static class Datum
	{
		public int[] ct;
		public int[] hist;
	}

	boolean[][] used;
	int[] ct;
	int[] hist;
	Map<Integer, Datum> ctmap;
	int[] map;
	char[][] b;
	int step;

	void rec(int r, int c)
	{
		if(r >= 7){
			int h = Arrays.hashCode(ct);
			if(!ctmap.containsKey(h)){
				Datum d = new Datum();
				d.ct = Arrays.copyOf(ct, 10);
				d.hist = Arrays.copyOf(hist, 28);
				ctmap.put(h, d);
			}
			return;
		}
		if(c >= 8){
			rec(r+1, 0);
			return;
		}
		if(used[r][c]){
			rec(r, c+1);
			return;
		}
		if(r+1 < 7 && !used[r+1][c]){
			used[r][c] = true;
			used[r+1][c] = true;
			int kind = map[(b[r][c]-'A')*26+(b[r+1][c]-'A')];
			ct[kind]++;
			hist[step] = r*8+c;
			step++;
			rec(r, c+1);
			step--;
			ct[kind]--;
			used[r][c] = false;
			used[r+1][c] = false;
		}
		if(c+1 < 8 && !used[r][c+1]){
			used[r][c] = true;
			used[r][c+1] = true;
			int kind = map[(b[r][c]-'A')*26+(b[r][c+1]-'A')];
			ct[kind]++;
			hist[step] = r*8+c+64;
			step++;
			rec(r, c+2);
			step--;
			ct[kind]--;
			used[r][c] = false;
			used[r][c+1] = false;
		}
	}

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

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

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

	public int ni()
	{
		try {
			int num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public long nl()
	{
		try {
			long num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public String ns()
	{
		try{
			int b = 0;
			StringBuilder sb = new StringBuilder();
			while((b = is.read()) != -1 && (b == '\r' || b == '\n' || b == ' '));
			if(b == -1)return "";
			sb.append((char)b);
			while(true){
				b = is.read();
				if(b == -1)return sb.toString();
				if(b == '\r' || b == '\n' || b == ' ')return sb.toString();
				sb.append((char)b);
			}
		} catch (IOException e) {
		}
		return "";
	}

	public char[] ns(int n)
	{
		char[] buf = new char[n];
		try{
			int b = 0, p = 0;
			while((b = is.read()) != -1 && (b == ' ' || b == '\r' || b == '\n'));
			if(b == -1)return null;
			buf[p++] = (char)b;
			while(p < n){
				b = is.read();
				if(b == -1 || b == ' ' || b == '\r' || b == '\n')break;
				buf[p++] = (char)b;
			}
			return Arrays.copyOf(buf, p);
		} catch (IOException e) {
		}
		return null;
	}

	double nd() { return Double.parseDouble(ns()); }
	boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


//package round93;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "BBWWRRYY\r\n" +
			"\r\n" +
			"WRRYYBBW\r\n" +
			"\r\n" +
			"WYBBWWRW\r\n" +
			"\r\n" +
			"BYWRRYRY\r\n" +
			"\r\n" +
			"BRWBBYBY\r\n" +
			"\r\n" +
			"WRYYWWBR\r\n" +
			"\r\n" +
			"WBBRRYYR\r\n" +
			"\r\n" +
			"0 0 0 7\r\n" +
			"\r\n" +
			"0 0 7\r\n" +
			"\r\n" +
			"0 7\r\n" +
			"\r\n" +
			"7";

	void solve()
	{
		b = new char[7][8];
		for(int i = 0;i < 7;i++){
			b[i] = ns(8);
		}
		int[] co = new int[10];
		for(int i = 0;i < 10;i++)co[i] = ni();

		String[] PILL = {
				"BY","BW","BR","BB",
				"RY","RW","RR",
				"WY","WW",
				"YY"
		};
		int[][] ctp = new int[10][26];
		for(int i = 0;i < 10;i++){
			for(int j = 0;j < 2;j++){
				ctp[i][PILL[i].charAt(j)-'A']++;
			}
		}

		int[][] C = new int[10][10];
		for(int i = 0;i < 10;i++){
			for(int j = 0;j < 10;j++){
				int tot = 0;
				for(int k = 0;k < 26;k++){
					tot += Math.min(ctp[i][k], ctp[j][k]);
				}
				C[i][j] = tot;
			}
		}

		map = new int[26*26];
		for(int i = 0;i < 10;i++){
			int f = PILL[i].charAt(0)-'A';
			int l = PILL[i].charAt(1)-'A';
			map[f*26+l] = i;
			map[l*26+f] = i;
		}
		used = new boolean[7][8];
		ct = new int[10];
		hist = new int[28];
		ctmap = new HashMap<Integer, Datum>();
		step = 0;

		rec(0, 0);

		int m = 10+100+10;
		int[] from = new int[m];
		int[] to = new int[m];
		int[] c = new int[m];
		int[] cap = new int[m];
		int O = 0;
		for(int i = 0;i < 10;i++){
			from[i+O] = 20; to[i+O] = i; c[i+O] = 0; cap[i+O] = 0; // Datum
		}
		O += 10;
		for(int i = 0;i < 10;i++){
			from[i+O] = i+10; to[i+O] = 21; c[i+O] = 0; cap[i+O] = co[i];
		}
		O += 10;
		for(int i = 0;i < 100;i++){
			from[i+O] = i/10; to[i+O] = i%10+10; c[i+O] = 2-C[i/10][i%10]; cap[i+O] = 999;
		}

		int[][][] cost = packWD(22, from, to, c);
		int[][][] capacity = packWD(22, from, to, cap);

		// unweighted invgraph
		// 逆グラフのcurのi番目=nextのとき、順グラフでcurはnextの何番目にあるかを返す
		int n = 22;
		int[][][] ig = new int[n][][];
		{
			int[] p = new int[n];
			for(int i = 0;i < n;i++){
				for(int j = 0;j < cost[i].length;j++)p[cost[i][j][0]]++;
			}
			for(int i = 0;i < n;i++)ig[i] = new int[p[i]][2];
			for(int i = n-1;i >= 0;i--){
				for(int j = 0;j < cost[i].length;j++){
					int u = --p[cost[i][j][0]];
					ig[cost[i][j][0]][u][0] = i;
					ig[cost[i][j][0]][u][1] = j;
				}
			}
		}

		int mincost = 999;
		int[] opthist = null;
		int[][] optF = new int[10][10];
		for(Datum d : ctmap.values()){
			for(int i = 0;i < 10;i++){
				capacity[20][9-i][1] = d.ct[i];
			}
			int mc = solveMinCostFlow(cost, capacity, ig, 20, 21, 28);
			if(mc < mincost){
				mincost = mc;
				opthist = d.hist;
				for(int i = 0;i < 10;i++){
					for(int j = 0;j < 10;j++){
						optF[i][j] = F[i][9-j][1];
					}
				}
			}
		}
//		tr(mincost);
//		tr(opthist);
//
//		int S = 0;
//		for(int i = 0;i < 10;i++){
//			for(int j = 0;j < 10;j++){
//				S += optF[i][j];
//			}
//		}
//		if(S != 28)throw new AssertionError(S);

		out.println(56-mincost);

		char[][] ret = new char[13][15];
		for(int i = 0;i < 13;i++){
			Arrays.fill(ret[i], '.');
		}

		for(int h : opthist){
			if(h < 64){
				// |
				int rr = h/8, cc = h%8;
				ret[rr*2+1][cc*2] = '|';

				int k = map[(b[rr][cc]-'A')*26+(b[rr+1][cc]-'A')];
				for(int i = 0;i < 10;i++){
					if(optF[k][i] > 0){
						if(flip(b[rr][cc], b[rr+1][cc], PILL[i].charAt(0), PILL[i].charAt(1))){
							ret[rr*2][cc*2] = PILL[i].charAt(1);
							ret[rr*2+2][cc*2] = PILL[i].charAt(0);
						}else{
							ret[rr*2][cc*2] = PILL[i].charAt(0);
							ret[rr*2+2][cc*2] = PILL[i].charAt(1);
						}
						optF[k][i]--;
						break;
					}
				}
			}else{
				h -= 64;
				// -
				int rr = h/8, cc = h%8;
				ret[rr*2][cc*2+1] = '-';

				int k = map[(b[rr][cc]-'A')*26+(b[rr][cc+1]-'A')];

				for(int i = 0;i < 10;i++){
					if(optF[k][i] > 0){
						if(flip(b[rr][cc], b[rr][cc+1], PILL[i].charAt(0), PILL[i].charAt(1))){
							ret[rr*2][cc*2] = PILL[i].charAt(1);
							ret[rr*2][cc*2+2] = PILL[i].charAt(0);
						}else{
							ret[rr*2][cc*2] = PILL[i].charAt(0);
							ret[rr*2][cc*2+2] = PILL[i].charAt(1);
						}
						optF[k][i]--;
						break;
					}
				}
			}
		}

		for(int i = 0;i < 13;i++){
			out.println(new String(ret[i]));
		}
	}

	static boolean flip(char a, char b, char c, char d)
	{
		int d1 = (a==c?1:0) + (b==d?1:0);
		int d2 = (a==d?1:0) + (b==c?1:0);
		return d2 > d1;
	}

	public static int[][][] packWD(int n, int[] from, int[] to, int[] w)
	{
		int[][][] g = new int[n][][];
		int[] p = new int[n];
		for(int f : from)p[f]++;
		for(int i = 0;i < n;i++)g[i] = new int[p[i]][2];
		for(int i = 0;i < from.length;i++){
			--p[from[i]];
			g[from[i]][p[from[i]]][0] = to[i];
			g[from[i]][p[from[i]]][1] = w[i];
		}
		return g;
	}

	int[][][] F;

	public int solveMinCostFlow(int[][][] cost, int[][][] capacity, int[][][] ig, int src, int sink, int all)
	{
		int n = cost.length;

		int[][][] flow = new int[n][][];
		for(int i = 0;i < n;i++) {
			flow[i] = new int[cost[i].length][2];
			for(int j = 0;j < cost[i].length;j++){
				flow[i][j][0] = cost[i][j][0];
			}
		}

		int mincost = 0;
		int[] pot = new int[n]; // ポテンシャル

		final int[] d = new int[n];
		TreeSet<Integer> q = new TreeSet<Integer>(new Comparator<Integer>(){
			public int compare(Integer a, Integer b)
			{
				if(d[a] - d[b] != 0)return d[a] - d[b];
				return a - b;
			}
		});
		while(all > 0){
			// src~sinkの最短路を探す
			int[] prev = new int[n];
			int[] myind = new int[n];
			Arrays.fill(prev, -1);
			Arrays.fill(d, Integer.MAX_VALUE / 2);
			d[src] = 0;
			q.clear();
			q.add(src);
			while(!q.isEmpty()){
				int cur = q.pollFirst();
				if(cur == sink)break;
				for(int i = 0;i < cost[cur].length;i++) {
					int next = cost[cur][i][0];
					if(capacity[cur][i][1] - flow[cur][i][1] > 0){
						int nd = d[cur] + cost[cur][i][1] + pot[cur] - pot[next];
						if(d[next] > nd){
							q.remove(next);
							d[next] = nd;
							prev[next] = cur;
							myind[next] = i;
							q.add(next);
						}
					}
				}
				for(int i = 0;i < ig[cur].length;i++) {
					int next = ig[cur][i][0];
					int cind = ig[cur][i][1];
					if(flow[next][cind][1] > 0){
						int nd = d[cur] - cost[next][cind][1] + pot[cur] - pot[next];
						if(d[next] > nd){
							q.remove(next);
							d[next] = nd;
							prev[next] = cur;
							myind[next] = -cind-1;
							q.add(next);
						}
					}
				}
			}

			if(prev[sink] == -1)break;

			int minflow = all;
			int sumcost = 0;
			for(int i = sink;i != src;i = prev[i]){
				if(myind[i] >= 0){
					minflow = Math.min(minflow, capacity[prev[i]][myind[i]][1] - flow[prev[i]][myind[i]][1]);
					sumcost += cost[prev[i]][myind[i]][1];
				}else{
					// cur->next
					// prev[i]->i
					// iが持ってる
					// ig[cur][j][0]=nextのときg[next][ig[cur][j][1]] = cur
					int ind = -myind[i]-1;
//					tr(prev[i], ind);
					minflow = Math.min(minflow, flow[i][ind][1]);
					sumcost -= cost[i][ind][1];
				}
			}

			mincost += minflow * sumcost;
			for(int i = sink;i != src;i = prev[i]){
				if(myind[i] >= 0){
					flow[prev[i]][myind[i]][1] += minflow;
				}else{
					int ind = -myind[i]-1;
					flow[i][ind][1] -= minflow;
				}
			}
//			tr(flow);

			all -= minflow;
			for(int i = 0;i < n;i++){
				pot[i] += d[i];
			}
		}
		F = flow;
		return mincost;
	}

	static class Datum
	{
		public int[] ct;
		public int[] hist;
	}

	boolean[][] used;
	int[] ct;
	int[] hist;
	Map<Integer, Datum> ctmap;
	int[] map;
	char[][] b;
	int step;

	void rec(int r, int c)
	{
		if(r >= 7){
			int h = Arrays.hashCode(ct);
			if(!ctmap.containsKey(h)){
				Datum d = new Datum();
				d.ct = Arrays.copyOf(ct, 10);
				d.hist = Arrays.copyOf(hist, 28);
				ctmap.put(h, d);
			}
			return;
		}
		if(c >= 8){
			rec(r+1, 0);
			return;
		}
		if(used[r][c]){
			rec(r, c+1);
			return;
		}
		if(r+1 < 7 && !used[r+1][c]){
			used[r][c] = true;
			used[r+1][c] = true;
			int kind = map[(b[r][c]-'A')*26+(b[r+1][c]-'A')];
			ct[kind]++;
			hist[step] = r*8+c;
			step++;
			rec(r, c+1);
			step--;
			ct[kind]--;
			used[r][c] = false;
			used[r+1][c] = false;
		}
		if(c+1 < 8 && !used[r][c+1]){
			used[r][c] = true;
			used[r][c+1] = true;
			int kind = map[(b[r][c]-'A')*26+(b[r][c+1]-'A')];
			ct[kind]++;
			hist[step] = r*8+c+64;
			step++;
			rec(r, c+2);
			step--;
			ct[kind]--;
			used[r][c] = false;
			used[r][c+1] = false;
		}
	}

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

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

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

	public int ni()
	{
		try {
			int num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public long nl()
	{
		try {
			long num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public String ns()
	{
		try{
			int b = 0;
			StringBuilder sb = new StringBuilder();
			while((b = is.read()) != -1 && (b == '\r' || b == '\n' || b == ' '));
			if(b == -1)return "";
			sb.append((char)b);
			while(true){
				b = is.read();
				if(b == -1)return sb.toString();
				if(b == '\r' || b == '\n' || b == ' ')return sb.toString();
				sb.append((char)b);
			}
		} catch (IOException e) {
		}
		return "";
	}

	public char[] ns(int n)
	{
		char[] buf = new char[n];
		try{
			int b = 0, p = 0;
			while((b = is.read()) != -1 && (b == ' ' || b == '\r' || b == '\n'));
			if(b == -1)return null;
			buf[p++] = (char)b;
			while(p < n){
				b = is.read();
				if(b == -1 || b == ' ' || b == '\r' || b == '\n')break;
				buf[p++] = (char)b;
			}
			return Arrays.copyOf(buf, p);
		} catch (IOException e) {
		}
		return null;
	}

	double nd() { return Double.parseDouble(ns()); }
	boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


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

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);
        n = in.nextInt();
        for (int i = 1; i <= n; i++) {
            g[i] = new ArrayList<>();
        }
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt(), v = in.nextInt();
            g[u].add(v);
            g[v].add(u);
        }
        dfs1(1, -1);
        int[] a = new int[2];
        int mx = n + 1;
        for (int i = 1; i <= n; i++) {
            if (msz[i] < mx) {
                mx = msz[i];
                a[0] = i;
                a[1] = -1;
            } else if (msz[i] == mx) {
                a[1] = i;
            }
        }
        root = a[0];
        for (int v : g[a[0]]) {
            if (v != a[1]) {
                goal = last = v;
                dfs2(v, a[0]);
                add(a[0], last, v);
            }
        }
        if (a[1] != -1) {
            root = a[1];
            for (int v : g[a[1]]) {
                if (v != a[0]) {
                    goal = last = v;
                    dfs2(v, a[1]);
                    add(a[1], last, v);
                }
            }
        }
        out.println(ans.size());
        for (int[] arr : ans) {
            out.println(arr[0] + " " + arr[1] + " " + arr[2]);
        }
        out.close();
    }

    static ArrayList<Integer>[] g = new ArrayList[200001];
    static int[] msz = new int[200001];
    static int[] sz = new int[200001];
    static int n;
    static ArrayList<int[]> ans = new ArrayList<>();
    static int goal;
    static int root;
    static int last;

    static void add(int x, int y, int z) {
        int[] t = {x, y, z};
        ans.add(t);
    }

    static void dfs1(int u, int fa) {
        sz[u] = 1;
        for (int v : g[u]) {
            if (v != fa) {
                dfs1(v, u);
                sz[u] += sz[v];
                msz[u] = Math.max(msz[u], sz[v]);
            }
        }
        msz[u] = Math.max(msz[u], n - sz[u]);
    }

    static void dfs2(int u, int fa) {
        if (u != goal) {
            add(root, last, u);
            add(u, fa, goal);
            last = u;
        }
        for (int v : g[u]) {
            if (v != fa) {
                dfs2(v, u);
            }
        }

    }

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

    }
}