// Timothy Buzzelli
// 2/21/2017
// Solution (with data verification) to 2017 FHSPS Playoff Question: Electric Car Race

import java.util.*;
import java.math.*;

public class electric_buzzelli {
    
    static int n, d, m;
    static int[][] dists;
    static Fraction[][][] memo;
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        // Read data and verify.
        String line = in.nextLine();
        String[] tokens = line.split(" ");
        if(tokens.length != 1) {
            System.err.println("Data invalid for c! Incorrect number of tokens!");
        }
        int c = Integer.parseInt(tokens[0]);
        if(c < 1 || c > 20) {
            System.err.printf("Input value for c is out of range! It is %d when it should be in the range [1, 20]\n", c);
        }
        
        // Process cases.
        for(int ci = 0; ci < c; ci++) {
        	
        	// Get case and verify input.
            line = in.nextLine();
            tokens = line.split(" ");
            if(tokens.length != 3) {
                System.err.println("Data invalid for n, m, and d! Incorrect number of tokens!");
            }
            
            // Top level data for case.
            n = Integer.parseInt(tokens[0]);
            m = Integer.parseInt(tokens[1]);
            d = Integer.parseInt(tokens[2]);
            
            // Check values.
            if(n < 1 || n > 10) {
                System.err.printf("Input value for n is out of range! It is %d when it should be in the range [1, 10]\n", n);
            }
            if(m < 0 || m > n) {
                System.err.printf("Input value for m is out of range! It is %d when it should be in the range [0, %d]\n", m, n);
            }
            if(d < 0 || d > 500) {
                System.err.printf("Input value for d is out of range! It is %d when it should be in the range [0, 500]\n", d);
            }
            
            // Store adjacency matrix.
            dists = new int[n + 1][n + 1];
            for(int i = 0; i < n + 1; i++) {
                line = in.nextLine();
                tokens = line.split(" ");
                if(tokens.length != n + 1) {
                    System.err.println("Data invalid for distances! Incorrect number of tokens!");
                }
                for(int j = 0; j < n + 1; j++) {
                    dists[i][j] = Integer.parseInt(tokens[j]);
                    if(dists[i][j] < 0 || dists[i][j] > 1000) {
                        System.err.printf("Input value for distance is out of range! It is %d when it should be in the range [0, 1000]\n", dists[i][j]);
                    }
                }
            }
            
            // memo[mask][i][j] stores probability of needing to visit mask ending at vertex i with j gas left.
            memo = new Fraction[1 << (n + 1)][n + 1][d + 1];
            Fraction ans = go((1 << (n + 1)) - 2, 0, d, n);
            System.out.printf("%s/%s\n", ans.n, ans.d);
        }
    }
    
    // Returns result for mask vertices visited, where we're at the vretex cur, with gas gas, and count count
    // of possible ways to get to this state.
    static Fraction go(int mask, int cur, int gas, int count) {
    	
    	// Ran out of gas probability is 0/1.
        if(gas < 0) return new Fraction(BigInteger.ZERO, BigInteger.ONE);
        if(cur <= m) gas = d;
        
        // Did this already.
        if(memo[mask][cur][gas] != null)
            return memo[mask][cur][gas];
            
        // Everything is visited.  
        if(mask == 0) {
        	
        	// Have enough gas to get here, probability is 1/1.
            if(gas >= dists[cur][0]) {
                return new Fraction(BigInteger.ONE, BigInteger.ONE);
            } 
            
            // Don't have enough gas, probability is 0/1.
            else {
                return new Fraction(BigInteger.ZERO, BigInteger.ONE);
            }
        }
        
        // Store my answer here.
        Fraction ans = new Fraction(BigInteger.ZERO, BigInteger.ONE);
        
        // i is next place to visit.
        for(int i = 1; i <= n; i++) {
        	
        	// Bit value of i.
            int a = 1 << i;
            
            // I've already been to i, so skip it.
            if((mask & a) == 0) continue;
            
            // Our new mask as we've now visited location i.
            int nm = mask ^ a;
            
            // Recursive result.
            Fraction tmp = go(nm, i, gas - dists[cur][i], count - 1);
            
            // This result is scaled by 1/count, where count is possible places to go.
            tmp = tmp.mult(new Fraction(BigInteger.ONE, BigInteger.valueOf(count)));
            
            // Add into my probability.
            ans = ans.add(tmp);
        }
        
        // Stores and return.
        return memo[mask][cur][gas] = ans;
    }
    
    // Fraction class of BigInteger numerator and denominator.
    static class Fraction {
        BigInteger n, d;
        public Fraction(BigInteger nn, BigInteger dd) {
            n = nn; d = dd;
            if(d.compareTo(BigInteger.ZERO) < 0) {
                n = n.negate();
                d = d.negate();
            }
            BigInteger gcd = n.gcd(d);
            n = n.divide(gcd);
            d = d.divide(gcd);
        }
        public Fraction add(Fraction f) {
            return new Fraction(n.multiply(f.d).add(f.n.multiply(d)), f.d.multiply(d));
        }
        
        public Fraction sub(Fraction f) {
            return new Fraction(n.multiply(f.d).subtract(f.n.multiply(d)), f.d.multiply(d));
        }
        public Fraction mult(Fraction f) {
            return new Fraction(n.multiply(f.n), f.d.multiply(d));
        }
        public Fraction divide(Fraction f) {
            return new Fraction(n.multiply(f.d), f.n.multiply(d));
        }
    }
    
}
