#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;

typedef vector<long double> V;
typedef vector<V> M;
const double eps=1e-8;

int h,w,mod;                    // 高さ, 幅, モジュロ
char input[50][50];             // 入力データ
int to_id[50][50];              // 座標からIDへのマッピング
int g[2500][4];                 // グラフ
int paf[2500][4];               // paffian orientation

int q[2500],qh,qt;              // キュー
int seen[2500];                 // バッファ

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};

int ox[4]={-1,0,0,-1};
int oy[4]={-1,-1,0,0};


/*
  ガウスの消去法で固有値を求める
 */
long double det(M& A) 
{
  int n=A.size();
  for (int k=0;k<n;++k) {
    int i,j;
    for(j=k;j<n;j++)
      for(i=k;i<n;i++)
        if (fabs(A[i][j])>eps) goto FOUND;
    break;
  FOUND:
    if (j!=k) for (int t=0;t<n;++t) swap(A[t][j], A[t][k]);
    if (i!=k) { swap(A[i],A[k]); }
    for (int j=k+1;j<n;++j)
      if (fabs(A[j][k])>eps) {
        double l=A[j][k]/A[k][k];
        for (int i=k+1;i<n;++i) A[j][i]=A[j][i]-(l*A[k][i]);
      }
  }

  double res=1;
  for (int i=0;i<n;++i)
    res*=A[i][i];
  return res;
}


/*
  Pfaffian orientationの確認
 */
void print_pfaffian() {
  for (int y=0;y<h;++y) {
    for (int x=0;x<w;++x) {
      putchar(input[y][x]);
      if (x!=w-1) {
        int id=to_id[y][x];
        if (id==-1) {
          putchar(' ');
        } else {
          if (paf[id][0]==1) {
            putchar('>');
          } else if (paf[id][0]==-1) {
            putchar('<');
          } else {
            putchar(' ');
          }
        }
      }
    }
    puts("");
    if (y!=h-1) {
      for (int x=0;x<w;++x) {
        int id=to_id[y][x];
        if (id==-1) {
          putchar(' ');
        } else {
          if (paf[id][1]==1) {
            putchar('v');
          } else if (paf[id][1]==-1) {
            putchar('^');
          } else {
            putchar(' ');
          }
        }

        if (x!=w-1) {
          putchar(' ');
        }
      }
      puts("");
    }
  }
}


int main() {
  int tmp;
  while(scanf("%d%d%d%d",&tmp,&h,&w,&mod)==4) {
    // 入力読み込み
    memset(to_id,-1,sizeof(to_id));
    int id_num=0;
    for (int y=0;y<h;++y)
      for (int x=0;x<w;++x) {
	assert(scanf(" %c",&input[y][x])==1);
        if (input[y][x]=='.') {
          to_id[y][x]=id_num++;
        }
      }

    // IDへ変換
    memset(g,-1,sizeof(g));
    for (int y=0;y<h;++y)
      for (int x=0;x<w;++x)
        for (int i=0;i<4;++i) {
          int nx=x+dx[i],ny=y+dy[i];
          if (nx<0||nx>=w) continue;
          if (ny<0||ny>=h) continue;
          g[to_id[y][x]][i]=to_id[ny][nx];
        }


    // Primalの全域木をBFSで辿る
    memset(seen,0,sizeof(seen));
    memset(paf,0,sizeof(paf));
    while(1) {
      qh=qt=0;
      for (int y=0;y<h&&qt==0;++y)
        for (int x=0;x<w&&qt==0;++x) {
          int id=to_id[y][x];
          if (input[y][x]=='.'&&!seen[id]) {
            q[qt++]=id;
            seen[id]=1;
          }
        }
      if (qt==0) break;

      while(qh!=qt) {
        int id=q[qh++];
        for (int i=0;i<4;++i) {
          int nid=g[id][i];
          if (nid!=-1&&!seen[nid]) {
            assert(paf[id][i]==0);
            paf[id][i]=1;
            paf[nid][(i+2)%4]=-1;
            q[qt++]=nid;
            seen[nid]=1;
          }
        }
      }
    }

    // Dualの全域木を葉から辿る
    int updated;
    do {
      updated=0;
      for (int y=1;y<h;++y)
        for (int x=1;x<w;++x){
          int ok=1;
          for (int i=0;i<4&&ok;++i) 
            if (input[y+oy[i]][x+ox[i]]=='*')
              ok=0;
          if (!ok) continue;

          int sum=0,abs_sum=0,ix=-1;
          for (int i=0;i<4;++i) {
            int cx=x+ox[i],cy=y+oy[i];
            int id=to_id[cy][cx];
            sum+=paf[id][i];
            abs_sum+=abs(paf[id][i]);
            if (paf[id][i]==0)
              ix=i;
          }
          if (abs_sum==3) {
            int cx=x+ox[ix],cy=y+oy[ix];
            int id=to_id[cy][cx];
            int nid=g[id][ix];
            int val=sum<0?abs(sum)-2:2-abs(sum);
            paf[id][ix]=val;
            paf[nid][(ix+2)%4]=-val;
            updated=1;
          }
        }
    } while(updated);

    // pfaffian orientationが出来ているか確認
    print_pfaffian();

    // 行列作成
    M A(id_num,V(id_num));
    for (int y=0;y<h;++y)
      for (int x=0;x<w;++x) {
        int id=to_id[y][x];
        if (id==-1) continue;
        for (int i=0;i<4;++i){
          int nid=g[id][i];
          if (nid==-1) continue;
          A[id][nid]=paf[id][i];
        }
      }
    printf("%d\n",(int)round(sqrt(abs(det(A))))%mod);
  }
}

