// Solution to "Efil" by Bob Roos
//
// This solution attempts to be "clever" to reduce the computation time,
// but it is still dog-slow for 4-by-5 grids. The basic idea is backtracking,
// but instead of filling in the parent candidate cell-by-cell, it is filled
// in with overlapping 3-by-3 configurations chosen from one of two lists,
// depending on whether we are trying to create a "live" cell or a "dead"
// cell from that 3-by-3 configuration. Thus, we start out by filling nine
// cells with a pattern, then we find a consistent overlapping pattern
// and fill six more cells, etc. But I think I need to do more preprocessing.
// For instance, I need a way to quickly look up all 9-bit patterns that
// contain a certain subpattern rather than doing a tedious "compatibility
// test" for each pattern added.
//
// Note to anyone reading this--I made a lot of false starts, so there is
// almost certainly some leftover useless code in here!


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

public class Efil {
 public static BufferedReader in;
 public static StringTokenizer tok;
 public static int m,n,k;
 public static int casenum;
 public static boolean goal[][];
 public static boolean used[][];
 public static int anc[][];
 public static int ancCount[][];
 public static String line;
 public static boolean alive[] = new boolean[512];
 public static int nbrCount[] = new int[512];
 public static int middle = 1<<4; // 000/010/000
 public static Vector nextlive;
 public static Vector nextdead;
 public static Hashtable nextStatus = new Hashtable();
 public static int numFilled;
 public static int numParents;

 public static void main(String[] args) throws IOException {
   in = new BufferedReader(new InputStreamReader(System.in));
   line = in.readLine().trim();
   tok = new StringTokenizer(line);
   m = Integer.parseInt(tok.nextToken());
   n = Integer.parseInt(tok.nextToken());
   casenum = 0;

   // Preprocessing -- store as much information as possible about
   // the 3x3 configurations.
   //
   // Each configuration is represented by the integer corresponding
   // to the 9-bit pattern represented by the 3x3 block of cells,
   // in row-major order. For each configuration, remember whether its
   // central cell is alive or dead, and how many live neighbors the
   // central cell has:

   nextlive = new Vector(); // nextlive and nextdead partition configs. by
   nextdead = new Vector(); // whether center cell is alive/dead in next gen.

   for (int i = 0; i < 512; i++) { // there are 2^9 3x3 configurations
     alive[i] = (i & middle) != 0; // is central cell alive?
     nbrCount[i] = 0;
     int nbrs = i & (~middle);
     for (int j = 0; j < 9; j++)
       if (((nbrs >> j) & 1) != 0)
         nbrCount[i]++;
     if (alive[i]) {
       if (nbrCount[i] >= 2 && nbrCount[i] <= 3) {
         nextlive.add(new Integer(i));
         nextStatus.put(new Integer(i),new Boolean(true));
       }
       else {
         nextdead.add(new Integer(i));
         nextStatus.put(new Integer(i),new Boolean(false));
       }
     }
     else {
       if (nbrCount[i] == 3) {
         nextlive.add(new Integer(i));
         nextStatus.put(new Integer(i),new Boolean(true));
       }
       else {
         nextdead.add(new Integer(i));
         nextStatus.put(new Integer(i),new Boolean(false));
       }
     }
   }


   // Main input/process/output loop:
   while (m >0 && n > 0) {
     casenum++;
     goal = new boolean[m][n]; // input configuration
     used = new boolean[m][n]; // is this cell accounted for in the parent?
     anc = new int[m][n];
     ancCount = new int[m][n]; // how many "active" goal cells depend on this?
     for (int i = 0; i < m; i++)
       for (int j = 0; j < n; j++) {
         goal[i][j] = false;
         used[i][j] = false;
         ancCount[i][j] = 0;
       }

     // Read in the positions of the occupied cells:
     k = Integer.parseInt(in.readLine().trim());
     for (int i = 0; i < k; i++) {
       line = in.readLine().trim();
       tok = new StringTokenizer(line);
       int r = Integer.parseInt(tok.nextToken());
       int c = Integer.parseInt(tok.nextToken());
       goal[r][c] = true;
     }

//debug(goal);
     process();

     // Get set up for next case:
     line = in.readLine().trim();
     tok = new StringTokenizer(line);
     m = Integer.parseInt(tok.nextToken());
     n = Integer.parseInt(tok.nextToken());
   }
 }

 // For debugging only: prints out the grid:
 public static void debug(boolean grid[][]) {
  System.out.print("+");
  for (int j = 0; j < n; j++)
    System.out.print("---+");
  System.out.println();
  for (int i = 0; i < m; i++) {
    System.out.print("|");
    for (int j = 0; j < n; j++)
      if (grid[i][j])
        System.out.print(" O |");
      else
        System.out.print("   |");
    System.out.println();
    System.out.print("+");
    for (int j = 0; j < n; j++)
      System.out.print("---+");
    System.out.println();
  }
 }

 // Mod function adjusted to always give nonnegative result:
 public static int mod(int a, int b) {
  int temp = a % b;
  if (temp < 0)
    temp += b;
  return temp;
 }

 // See if the 3x3 ancestor candidate pattern is compatible with the
 // 3x3 portion of the ancestor grid centered at (r,c).

 public static boolean compatible(int pattern, int r, int c) {
  // Special cases:
  if (m == 1) {
    if ((pattern & 7) != ((pattern >> 3) & 7))
      return false;
    if ((pattern & 7) != ((pattern >> 6) & 7))
      return false;
    if (((pattern >> 3) & 7) != ((pattern >> 6) & 7))
      return false;
  }
  if (m == 2) {
    if ((pattern & 7) != ((pattern >> 6) & 7))
       return false;
  }
  if (n == 1) {
    if ((pattern & 73) != ((pattern >> 1) & 73))
       return false;
    if ((pattern & 73) != ((pattern >> 2) & 73))
       return false;
    if (((pattern >> 1) & 73) != ((pattern >> 2) & 73))
       return false;
  }
  if (n == 2) {
    if ((pattern & 73) != ((pattern >> 2) & 73))
      return false;
  }

  int temp = 0;
  int pos = 8;
  int mask = 0;
  for (int i = r-1; i <= r+1; i++)
    for (int j = c-1; j <= c+1; j++) {
      int i1 = mod(i,m);
      int j1 = mod(j,n);
      if (used[i1][j1]) { // if this cell in the ancestor grid is used, ...
        temp += anc[i1][j1]<<pos; // ... copy it...
        mask += 1<<pos; // ... and include it in the compatibility test
      }
      pos--;
    }
  return (pattern & mask) == (temp & mask); // don't need second "& mask"!
 }

 // Fill the 3x3 portion of the ancestor grid centered at r,c with
 // the 3x3 pattern; assume that the pattern is compatible, i.e.,
 // assume previous call to "compatible(pattern,r,c)" succeeded:

  public static void fill(int pattern, int r, int c) {
    int pos = 8;
    for (int i = r-1; i <= r+1; i++) {
      for (int j = c-1; j <= c+1; j++) {
        int i1 = mod(i,m);
        int j1 = mod(j,n);
        if (used[i1][j1]){
          ancCount[i1][j1]++;
        }
        else {
          used[i1][j1] = true;
          anc[i1][j1] = 1 & (pattern >> pos);
          ancCount[i1][j1] = 1;
          numFilled++;
        }
        pos--;
      }
    }
  }

 // "Unfill" the 3x3 portion of the ancestor grid centered at r,c with
 // the 3x3 pattern; assume that the pattern is compatible, i.e.,
 // assume previous call to "compatible(pattern,r,c)":

 public static void unfill(int pattern, int r, int c) {
  int pos = 8;
  for (int i = r-1; i <= r+1; i++) {
    for (int j = c-1; j <= c+1; j++) {
      int i1 = mod(i,m);
      int j1 = mod(j,n);
        if (used[i1][j1]){
        ancCount[i1][j1]--;
        if (ancCount[i1][j1] <= 0) {
           used[i1][j1] = false;
           numFilled--;
        }
      }
      else {
        System.out.println("Error in unfill -- unable to undo from ["
          + i1 + "]["+j1+"]");
      }
      pos--;
    }
  }
 }


  public static void process() {
    numFilled = 0;
    numParents = 0;
    // start recursive backtracking to fill in grid:
    recursiveFill(0,0);
    if (numParents > 0)
      System.out.println("Case " + casenum +": "+ numParents
             + " possible ancestors.");
    else
      System.out.println("Case " + casenum + ": Garden of Eden.");
  }

  public static void recursiveFill(int r, int c) {
    Vector choices;
    if (goal[r][c])
      choices = nextlive;
    else
      choices = nextdead;

    for (int i = 0; i < choices.size(); i++) {
      int pattern = ((Integer)(choices.get(i))).intValue();
      if (compatible(pattern,r,c)) {
        fill(pattern,r,c);
        if (numFilled == m*n) {
          if (verify())
            numParents++;
        }
        else {
          boolean found = false;
          int nextRow = r;
          int nextCol = c+1;
          if (nextCol >= n) {
            nextRow++; nextCol = 0;
          }
          boolean skip = false;
          while (!found) {
            if (!used[nextRow][nextCol]) {
              break;
            }

// LAST DITCH ATTEMPT FOR AN "EASY" SPEED UP (NOT MUCH USE):
// this cell is used, so see if we can prune the search:
boolean check = true;
for (int p = nextRow-1; p <= nextRow+1; p++)
  for (int q = nextCol-1; q <= nextCol+1; q++) {
     int p1 = mod(p,m);
     int q1 = mod(q,n);
     if (!used[p1][q1])
       check = false;
  }
if (check && !((Boolean)(nextStatus.get(new Integer(bitpattern(nextRow,nextCol))))
                 .equals(new Boolean(goal[nextRow][nextCol])))) {
   skip = true;
   break;
}

            nextCol++;
            if (nextCol >= n) {
              nextRow++; nextCol = 0;
            }
          }
          if (!skip)
            recursiveFill(nextRow, nextCol);
        }
        unfill(pattern,r,c);
      }
    }
  }

  public static int bitpattern(int r, int c) {
    int pos = 8;
    int temp = 0;
    for (int i = r-1; i <= r+1; i++)
      for (int j = c-1; j <= c+1; j++) {
        int i1 = mod(i,m);
        int j1 = mod(j,n);
        temp += anc[i1][j1]<<pos;
        pos--;
      }
    return temp;
  }

  public static boolean verify() {
    for (int i = 0; i < m; i++) {
      for (int j = 0; j < n; j++) {
        int temp = bitpattern(i,j);
        Boolean status = (Boolean)nextStatus.get(new Integer(temp));
        if (status.booleanValue() && !goal[i][j])
           return false;
        if (!status.booleanValue() && goal[i][j])
           return false;
      }
    }
    return true;
  }
}
