// Solution for BHCSI 2007 Contest Problem Math Blaster
// Written by Rose Nestor, edited by Arup Guha

// Note: The data for this problem is EXTREMELY WEAK!!!
// It was 2:30am when I reviewed the problem and there were only two test cases.
// I was really, really lazy and just added one more, (which incidentally did
// catch one team.) If you look at the test data, what you can see is that
// more cases needed to be added that thoroughly test out possibilities of
// arithmetic expressions. Furthermore, more combinations of attacks should be
// tried out.

import java.io.*;
import java.util.*;


public class mathblas {
	
	static int  num; // num attacks
	static int hp;
	static int min;
	static int round;
	static String [][] att;
	
	
	public static void main(String args[])
	{
		round=0;
		try {
			Scanner fin = new Scanner(new File("mathblas.in"));
			
			int numcases = fin.nextInt();
			String dummy = fin.nextLine();
			
			for (int mycase=1; mycase<=numcases; mycase++)
			{
				round++;
				num = parseExpression(fin.nextLine()) + 1; // have to include MinusSlash
				// System.out.println("" + num);
				att = new String[num][2];
				att[0][0]="MinusSlash";
				att[0][1]="1";
				
				for (int i = 1; i<num;i++)
					parseAttack(fin.nextLine(),i);
				
				hp = parseExpression(fin.nextLine());
				// System.out.println("" + hp);
				
				insertionSortAttacks();
				// printAttacks();
				min = change();
				
				print(mycase);
			}
		} catch (java.io.FileNotFoundException e)
		{ }
	}
	
	public static int parseExpression(String line){
		int value;
		// System.out.println(line);
		line.trim();
		String[] ints = line.split("\\W"); //non-word char (non-digit)  separates
		// String[] ops = line.split("^+-/*"); // word char separates
		// why is ops[0] a space?
		
		String[] ops = new String[ints.length-1];
		int counter=0;
		for (int i=0;i<line.length();i++)
		{
			if (!Character.isDigit(line.charAt(i))){
				ops[counter]=Character.toString(line.charAt(i));
				counter++;
			}
				
		}
				
		value = Integer.parseInt(ints[0]);
		
		for (int i=1;i<ints.length;i++)
		{
			switch((ops[i-1].toCharArray())[0])
			{
				case '+':
					value += Integer.parseInt(ints[i]);
					break;
				case '*':
					value *= Integer.parseInt(ints[i]);
					break;
				case '-':
					value -= Integer.parseInt(ints[i]);
					break;
				case '/':
					value /= Integer.parseInt(ints[i]);
					break;
			}
		}
		
		return value;
	}
	
	public static void parseAttack(String line, int i){
		String[] temp = line.split("\\s"); // whitespace char
		att[i][0] = temp[0];
		att[i][1] = "" + parseExpression(temp[1]);
	}
	
	
	public static void print(int mycase)
	{
			System.out.println("Case #" + mycase+":");
			System.out.println("Math Blaster's Attacks:");
			

			printAttacks();
			
			System.out.println("\n" + min + " combinations of attacks can deplete "
				+ hp + " HP\n");
	}
	
   public static void insertionSortAttacks()
   {
	
	   for(int out=1; out<num; out++)   
	     {
	     String tStr = att[out][0];
	     int tInt = Integer.parseInt(att[out][1]);     
	     	 
	     int in = out;           
	     while(in>0 && Integer.parseInt(att[in-1][1]) >= tInt) 
	      {
	      att[in][0] = att[in-1][0];      
	      att[in][1] = att[in-1][1];
	      --in;            
	      }
	     att[in][1] = "" + tInt;
	     att[in][0] = tStr;
	     
	     
	     } 
	     return;
   }
   
   public static void printAttacks()
   {
   		for (int i=0;i<num;i++) 
   			System.out.println(att[i][0] + " " + att[i][1]);
   			
   		return;
   			
   }

	public static int change() {


		int[][] t = new int[num][hp+1];
		if (hp<=0)
			return 1;
      else if (hp==1)
          return 1;
       else if ((hp>=0) && (hp < Integer.parseInt(att[1][1])))
        	return 1;
    
       
       else {

			// I used Arup's method of pre-filling the values for columns below the first non-one denomination
           
           // Sets first rows to 1 because you can only add up single hit points in one way.
           for (int i=0;i<=hp;i++)
            	t[0][i]=1;   	
           
           // Here we are initializing the table to say that if we trying to find a combo
           // that adds up to less than X points, where X is the value of our second smallest
           // attack, then we can also only do that in one way.
           for (int i=0; i<Integer.parseInt(att[1][1]); i++) {
                for (int j=1;j<num;j++)
                {
               
                	t[j][i] = 1;
             
                }
            }
        
           for (int i=1; i<num; i++) {
                for (int j=Integer.parseInt(att[1][1]); j<=hp; j++) {
                	
                	// Alternate solution is to replace this loop with
                	// the following statement:
                	// This is what was shown in class.
                	/* 
                	if (j >= Integer.parseInt(att[i][1]))
                		t[i][j] = t[i-1][j] + t[i][j - Integer.parseInt(att[i][1])];
                	else
                		t[i][j] = t[i-1][j];
                	*/
                		
                    for (int k=0; k<=i; k++) {
                        if ( j >= Integer.parseInt(att[k][1])) //////
                        	// Integer.parseInt(att[k][1]) = attack value
                             t[i][j] += t[k][j - Integer.parseInt(att[k][1])];
                    } 
                    
                }
            }        
  			
       }
       return t[num-1][hp]; 
	}

}