#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
  cin.tie(nullptr); // Do not flush "cout" when processing "cin".

  int n, k;
  cin >> n >> k;

  vector<vector<int>> t(8, vector<int>(8));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      cin >> t.at(i).at(j);
    }
  }

  // 都市番号は 0-indexed とする。
  // 都市番号が 1 〜 n-1 の都市について、全ての順列を試す。
  //
  // p の要素番号は 0 〜 n-2 となる。
  vector<int> p;
  for (int i = 1; i < n; i++) {
    p.push_back(i);
  }

  int ans = 0;
  do {
    // 都市 0 から都市 p[0] までの移動距離
    int total = t.at(0).at(p.at(0));
    // 都市 p[0] から都市 p[1] への移動時間
    // ...
    // 都市 p[n-3] から都市 p[n-2] への移動時間
    //
    // 上記の移動時間をそれぞれ加算する。
    for (int i = 0; i < n - 2; i++) {
      int from = p.at(i);
      int to = p.at(i + 1);
      total += t.at(from).at(to);
    }
    // 都市 p[n-2] から都市 0 への移動時間
    total += t.at(p.at(n - 2)).at(0);

    if (total == k) {
      ans++;
    }
    // ### next_permutation
    //
    // 今回の場合、vector コンテナクラスのメンバ変数である
    // vector<int>::iterator 型の値を引数に取る。
    //
    // [first, last) で指定した区間の要素を順列に並べ替える。
    // そのため、next_permutation の第一引数を p.begin() + 1
    // とする場合、0 番目の要素は並べ替えられない。
    //
    // また、next_permutation は次の順列を生成することができる場合、
    // true、生成できない場合は false を返す。
    //
    // next_permutation は辞書順に並び替えて順列を生成する。
    // そのため、以下の例では {1, 2, 3}, {1, 3, 2} の組み合わせは生成されない。
    // {2, 1, 3} の次は、辞書順で {2, 3, 1} が生成される。
    //
    //   vector<int> v = {2, 1, 3};
    //   do {
    //     ...
    //   } while (next_permutation(v.begin(), v.end()));
    //
    // 次の順列が生成できなくなった時点で vector コンテナは
    // 辞書順の最後の並びとなっている。
    //
    //   上記 v = {2, 1, 3} の例では、
    //   v = {3, 2, 1} に並び替えられている。
    //
    // おそらく、順列が生成できず false を返すタイミングで、
    // vector コンテナの要素を reverse(v.begin(), v.end()) で
    // 辞書順の最初の並びにしている。
    //
    //   上記例では v = {3, 2, 1} を
    //   v = {1, 2, 3} にしている。
    //
    // これより do-while の実行前に vector の要素を予め
    // sort している場合は、do-while 終了後に vector の値が
    // 元に戻っている（あるいは、do-while ブロック内でのみ
    // 順番が変更されている）ように見える。
    //
  } while (next_permutation(p.begin(), p.end()));

  cout << ans << endl;
  return 0;
}

const bool isDebugMode = true;
int testcase = 1;
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
    #include <atcoder/all>
    using namespace atcoder;
#endif
using namespace std;
typedef long long ll;
typedef pair<long long, long long> P;
struct edge{long long to,cost;};
const int inf = 1 << 27;
const long long INF = 1LL << 60;
const int COMBMAX = 1001001;
const int SHOWSIZE = 1 << 5;
const long long MOD = 1000000007; //998244353;
const long long dy[] = {0, 0, 1, 1};
const long long dx[] = {0, 1, 0, 1};
const string abc = "abcdefghijklmnopqrstuvwxyz";
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define eachdo(v, e) for (const auto &e : (v))
#define all(v) (v).begin(), (v).end()
#define lower_index(v, e) (long long)distance((v).begin(), lower_bound((v).begin(), (v).end(), e))
#define upper_index(v, e) (long long)distance((v).begin(), upper_bound((v).begin(), (v).end(), e))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
long long mpow(long long a, long long n, long long mod = MOD){long long res = 1; while(n > 0){if(n & 1)res = res * a % mod; a = a * a % mod; n >>= 1;} return res;}
long long power(long long a, long long n){long long res = 1; while(n > 0){if(n & 1)res = res * a; a = a * a; n >>= 1;} return res;}
void pt(){cout << endl; return;}
template<class Head> void pt(Head&& head){cout << head; pt(); return;}
template<class Head, class... Tail> void pt(Head&& head, Tail&&... tail){cout << head << " "; pt(forward<Tail>(tail)...);}
void dpt(){if(!isDebugMode) return; cout << endl; return;}
template<class Head> void dpt(Head&& head){if(!isDebugMode) return; cout << head; pt(); return;}
template<class Head, class... Tail> void dpt(Head&& head, Tail&&... tail){if(!isDebugMode) return; cout << head << " "; pt(forward<Tail>(tail)...);}
template<class T> void enu(T v){rep(i, v.size()) cout << v[i] << " " ; cout << endl;}
template<class T> void enu2(T v){rep(i, v.size()){rep(j, v[i].size()) cout << v[i][j] << " " ; cout << endl;}}
template<class T> void debug(T v){if(!isDebugMode) return; rep(i, min(v.size(), SHOWSIZE)) cout << v[i] << " " ; cout << endl;}
template<class T> void debug2(T v){if(!isDebugMode) return; rep(i, min(v.size(), SHOWSIZE)){rep(j, min(v[i].size(), SHOWSIZE)) cout << v[i][j] << " " ; cout << endl;}}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b){if(a > b){a = b; return true;} return false;}
template<class T1, class T2> inline bool chmax(T1 &a, T2 b){if(a < b){a = b; return true;} return false;}
template<class T1, class T2> long long recgcd(T1 a, T2 b){return a % b ? recgcd(b, a % b) : b;}
template<typename T> vector<T> make_v(size_t a){return vector<T>(a);}
template<typename T,typename... Ts> auto make_v(size_t a,Ts... ts){return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));}
template <typename T, typename U, typename... V> typename enable_if<is_same<T, U>::value != 0>::type fill_v(U &u, const V... v) { u = U(v...); }
template <typename T, typename U, typename... V> typename enable_if<is_same<T, U>::value == 0>::type fill_v(U &u, const V... v){for (auto &e : u) fill_v<T>(e, v...);}
bool valid(long long H, long long W, long long h, long long w) { return 0 <= h && h < H && 0 <= w && w < W; }

void solve();

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    // cin >> testcase;
    while(testcase--) solve();
    return 0;
}

void solve(){
    ll H, W; cin >> H >> W;
    vector<string> s(H);
    rep(i, H) cin >> s[i];
    ll ans = 0;
    rep(i, H - 1)rep(j, W - 1){
        ll cnt = 0;
        rep(k, 4){
            if(valid(H, W, i + dx[k], j + dy[k]) && s[i + dx[k]][j + dy[k]] == '.') cnt++;
        }
        if(cnt % 2) ans++;
    }
    pt(ans);
}